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.

9160 lines
263 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. network.c
  5. Abstract:
  6. Implements the Node Manager's network management routines.
  7. Author:
  8. Mike Massa (mikemas) 7-Nov-1996
  9. Revision History:
  10. --*/
  11. #include "nmp.h"
  12. /////////////////////////////////////////////////////////////////////////////
  13. //
  14. // Data
  15. //
  16. /////////////////////////////////////////////////////////////////////////////
  17. ULONG NmpNextNetworkShortId = 0;
  18. LIST_ENTRY NmpNetworkList = {NULL, NULL};
  19. LIST_ENTRY NmpInternalNetworkList = {NULL, NULL};
  20. LIST_ENTRY NmpDeletedNetworkList = {NULL, NULL};
  21. DWORD NmpNetworkCount = 0;
  22. DWORD NmpInternalNetworkCount = 0;
  23. DWORD NmpClientNetworkCount = 0;
  24. BOOLEAN NmpIsConnectivityReportWorkerRunning = FALSE;
  25. BOOLEAN NmpNeedConnectivityReport = FALSE;
  26. CLRTL_WORK_ITEM NmpConnectivityReportWorkItem;
  27. RESUTIL_PROPERTY_ITEM
  28. NmpNetworkProperties[] =
  29. {
  30. {
  31. L"Id", NULL, CLUSPROP_FORMAT_SZ,
  32. 0, 0, 0,
  33. 0,
  34. FIELD_OFFSET(NM_NETWORK_INFO, Id)
  35. },
  36. {
  37. CLUSREG_NAME_NET_NAME, NULL, CLUSPROP_FORMAT_SZ,
  38. 0, 0, 0,
  39. 0,
  40. FIELD_OFFSET(NM_NETWORK_INFO, Name)
  41. },
  42. {
  43. CLUSREG_NAME_NET_DESC, NULL, CLUSPROP_FORMAT_SZ,
  44. (DWORD_PTR) NmpNullString, 0, 0,
  45. 0,
  46. FIELD_OFFSET(NM_NETWORK_INFO, Description)
  47. },
  48. {
  49. CLUSREG_NAME_NET_ROLE, NULL, CLUSPROP_FORMAT_DWORD,
  50. ClusterNetworkRoleClientAccess,
  51. ClusterNetworkRoleNone,
  52. ClusterNetworkRoleInternalAndClient,
  53. 0,
  54. FIELD_OFFSET(NM_NETWORK_INFO, Role)
  55. },
  56. {
  57. CLUSREG_NAME_NET_PRIORITY, NULL, CLUSPROP_FORMAT_DWORD,
  58. 0, 0, 0xFFFFFFFF,
  59. 0,
  60. FIELD_OFFSET(NM_NETWORK_INFO, Priority)
  61. },
  62. {
  63. CLUSREG_NAME_NET_TRANSPORT, NULL, CLUSPROP_FORMAT_SZ,
  64. 0, 0, 0,
  65. 0,
  66. FIELD_OFFSET(NM_NETWORK_INFO, Transport)
  67. },
  68. {
  69. CLUSREG_NAME_NET_ADDRESS, NULL, CLUSPROP_FORMAT_SZ,
  70. 0, 0, 0,
  71. 0,
  72. FIELD_OFFSET(NM_NETWORK_INFO, Address)
  73. },
  74. {
  75. CLUSREG_NAME_NET_ADDRESS_MASK, NULL, CLUSPROP_FORMAT_SZ,
  76. 0, 0, 0,
  77. 0,
  78. FIELD_OFFSET(NM_NETWORK_INFO, AddressMask)
  79. },
  80. {
  81. 0
  82. }
  83. };
  84. /////////////////////////////////////////////////////////////////////////////
  85. //
  86. // Initialization & cleanup routines
  87. //
  88. /////////////////////////////////////////////////////////////////////////////
  89. DWORD
  90. NmpInitializeNetworks(
  91. VOID
  92. )
  93. /*++
  94. Routine Description:
  95. Initializes network resources.
  96. Arguments:
  97. None.
  98. Return Value:
  99. A Win32 status value.
  100. --*/
  101. {
  102. DWORD status;
  103. OM_OBJECT_TYPE_INITIALIZE networkTypeInitializer;
  104. ClRtlLogPrint(LOG_NOISE,"[NM] Initializing networks.\n");
  105. //
  106. // Create the network object type
  107. //
  108. ZeroMemory(&networkTypeInitializer, sizeof(OM_OBJECT_TYPE_INITIALIZE));
  109. networkTypeInitializer.ObjectSize = sizeof(NM_NETWORK);
  110. networkTypeInitializer.Signature = NM_NETWORK_SIG;
  111. networkTypeInitializer.Name = L"Network";
  112. networkTypeInitializer.DeleteObjectMethod = &NmpDestroyNetworkObject;
  113. status = OmCreateType(ObjectTypeNetwork, &networkTypeInitializer);
  114. if (status != ERROR_SUCCESS) {
  115. WCHAR errorString[12];
  116. wsprintfW(&(errorString[0]), L"%u", status);
  117. CsLogEvent1(LOG_CRITICAL, CS_EVENT_ALLOCATION_FAILURE, errorString);
  118. ClRtlLogPrint(LOG_CRITICAL,
  119. "[NM] Unable to create network object type, status %1!u!\n",
  120. status
  121. );
  122. return(status);
  123. }
  124. return(status);
  125. } // NmpInitializeNetworks
  126. VOID
  127. NmpCleanupNetworks(
  128. VOID
  129. )
  130. /*++
  131. Routine Description:
  132. Destroys all existing network resources.
  133. Arguments:
  134. None.
  135. Return Value:
  136. None.
  137. --*/
  138. {
  139. PNM_NETWORK network;
  140. PLIST_ENTRY entry;
  141. DWORD status;
  142. ClRtlLogPrint(LOG_NOISE,"[NM] Network cleanup starting...\n");
  143. //
  144. // Now clean up all the network objects.
  145. //
  146. NmpAcquireLock();
  147. while (!IsListEmpty(&NmpNetworkList)) {
  148. entry = NmpNetworkList.Flink;
  149. network = CONTAINING_RECORD(entry, NM_NETWORK, Linkage);
  150. CL_ASSERT(NM_OM_INSERTED(network));
  151. NmpDeleteNetworkObject(network, FALSE);
  152. }
  153. NmpMulticastCleanup();
  154. NmpReleaseLock();
  155. ClRtlLogPrint(LOG_NOISE,"[NM] Network cleanup complete\n");
  156. return;
  157. } // NmpCleanupNetworks
  158. /////////////////////////////////////////////////////////////////////////////
  159. //
  160. // Top-level routines called during network configuration
  161. //
  162. /////////////////////////////////////////////////////////////////////////////
  163. DWORD
  164. NmpCreateNetwork(
  165. IN RPC_BINDING_HANDLE JoinSponsorBinding,
  166. IN PNM_NETWORK_INFO NetworkInfo,
  167. IN PNM_INTERFACE_INFO2 InterfaceInfo
  168. )
  169. /*++
  170. Notes:
  171. Must not be called with NM lock held.
  172. --*/
  173. {
  174. DWORD status;
  175. if (JoinSponsorBinding != NULL) {
  176. //
  177. // We are joining a cluster. Ask the sponsor to add the definition
  178. // to the cluster database. The sponsor will also prompt all active
  179. // nodes to instantiate a corresponding object. The object will be
  180. // instantiated locally later in the join process.
  181. //
  182. status = NmRpcCreateNetwork2(
  183. JoinSponsorBinding,
  184. NmpJoinSequence,
  185. NmLocalNodeIdString,
  186. NetworkInfo,
  187. InterfaceInfo
  188. );
  189. }
  190. else if (NmpState == NmStateOnlinePending) {
  191. HLOCALXSACTION xaction;
  192. //
  193. // We are forming a cluster. Add the definitions to the database.
  194. // The corresponding object will be created later in
  195. // the form process.
  196. //
  197. //
  198. // Start a transaction - this must be done before acquiring the
  199. // NM lock.
  200. //
  201. xaction = DmBeginLocalUpdate();
  202. if (xaction == NULL) {
  203. status = GetLastError();
  204. ClRtlLogPrint(LOG_CRITICAL,
  205. "[NM] Failed to start a transaction, status %1!u!\n",
  206. status
  207. );
  208. return(status);
  209. }
  210. status = NmpCreateNetworkDefinition(NetworkInfo, xaction);
  211. if (status == ERROR_SUCCESS) {
  212. status = NmpCreateInterfaceDefinition(InterfaceInfo, xaction);
  213. }
  214. //
  215. // Complete the transaction - this must be done after releasing
  216. // the NM lock.
  217. //
  218. if (status == ERROR_SUCCESS) {
  219. DmCommitLocalUpdate(xaction);
  220. }
  221. else {
  222. DmAbortLocalUpdate(xaction);
  223. }
  224. }
  225. else {
  226. //
  227. // We are online. This is a PnP update.
  228. //
  229. NmpAcquireLock();
  230. status = NmpGlobalCreateNetwork(NetworkInfo, InterfaceInfo);
  231. NmpReleaseLock();
  232. }
  233. return(status);
  234. } // NmpCreateNetwork
  235. DWORD
  236. NmpSetNetworkName(
  237. IN PNM_NETWORK_INFO NetworkInfo
  238. )
  239. /*++
  240. Notes:
  241. Must not be called with NM lock held.
  242. --*/
  243. {
  244. DWORD status;
  245. if (NmpState == NmStateOnlinePending) {
  246. HLOCALXSACTION xaction;
  247. //
  248. // We are forming a cluster. The local connectoid name has
  249. // precedence. Fix the cluster network name stored in the
  250. // cluster database.
  251. //
  252. //
  253. // Start a transaction - this must be done before acquiring the
  254. // NM lock.
  255. //
  256. xaction = DmBeginLocalUpdate();
  257. if (xaction == NULL) {
  258. status = GetLastError();
  259. ClRtlLogPrint(LOG_CRITICAL,
  260. "[NM] Failed to start a transaction, status %1!u!\n",
  261. status
  262. );
  263. return(status);
  264. }
  265. status = NmpSetNetworkNameDefinition(NetworkInfo, xaction);
  266. //
  267. // Complete the transaction - this must be done after releasing
  268. // the NM lock.
  269. //
  270. if (status == ERROR_SUCCESS) {
  271. DmCommitLocalUpdate(xaction);
  272. }
  273. else {
  274. DmAbortLocalUpdate(xaction);
  275. }
  276. }
  277. else {
  278. //
  279. // We are online. This is either a PnP update or we were called
  280. // back to indicate that a local connectoid name changed.
  281. // Issue a global update to set the cluster network name accordingly.
  282. //
  283. status = NmpGlobalSetNetworkName( NetworkInfo );
  284. }
  285. return(status);
  286. } // NmpSetNetworkName
  287. /////////////////////////////////////////////////////////////////////////////
  288. //
  289. // Remote procedures called by joining nodes.
  290. //
  291. /////////////////////////////////////////////////////////////////////////////
  292. error_status_t
  293. s_NmRpcCreateNetwork(
  294. IN handle_t IDL_handle,
  295. IN DWORD JoinSequence, OPTIONAL
  296. IN LPWSTR JoinerNodeId, OPTIONAL
  297. IN PNM_NETWORK_INFO NetworkInfo,
  298. IN PNM_INTERFACE_INFO InterfaceInfo1
  299. )
  300. {
  301. DWORD status;
  302. NM_INTERFACE_INFO2 interfaceInfo2;
  303. //
  304. // Translate and call the V2.0 procedure. The NetIndex isn't used in this call.
  305. //
  306. CopyMemory(&interfaceInfo2, InterfaceInfo1, sizeof(NM_INTERFACE_INFO));
  307. interfaceInfo2.AdapterId = NmpUnknownString;
  308. interfaceInfo2.NetIndex = NmInvalidInterfaceNetIndex;
  309. status = s_NmRpcCreateNetwork2(
  310. IDL_handle,
  311. JoinSequence,
  312. JoinerNodeId,
  313. NetworkInfo,
  314. &interfaceInfo2
  315. );
  316. return(status);
  317. } // s_NmRpcCreateNetwork
  318. error_status_t
  319. s_NmRpcCreateNetwork2(
  320. IN handle_t IDL_handle,
  321. IN DWORD JoinSequence, OPTIONAL
  322. IN LPWSTR JoinerNodeId, OPTIONAL
  323. IN PNM_NETWORK_INFO NetworkInfo,
  324. IN PNM_INTERFACE_INFO2 InterfaceInfo
  325. )
  326. {
  327. DWORD status = ERROR_SUCCESS;
  328. ClRtlLogPrint(LOG_NOISE,
  329. "[NMJOIN] Received request to create new network %1!ws! for "
  330. "joining node.\n",
  331. NetworkInfo->Id
  332. );
  333. NmpAcquireLock();
  334. if (NmpLockedEnterApi(NmStateOnline)) {
  335. PNM_NODE joinerNode = NULL;
  336. if (lstrcmpW(JoinerNodeId, NmpInvalidJoinerIdString) != 0) {
  337. joinerNode = OmReferenceObjectById(
  338. ObjectTypeNode,
  339. JoinerNodeId
  340. );
  341. if (joinerNode != NULL) {
  342. if ( (JoinSequence == NmpJoinSequence) &&
  343. (NmpJoinerNodeId == joinerNode->NodeId) &&
  344. (NmpSponsorNodeId == NmLocalNodeId) &&
  345. !NmpJoinAbortPending
  346. )
  347. {
  348. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  349. CL_ASSERT(NmpJoinerUp == FALSE);
  350. CL_ASSERT(NmpJoinTimer != 0);
  351. //
  352. // Suspend the join timer while we are working on
  353. // behalf of the joiner. This precludes an abort
  354. // from occuring as well.
  355. //
  356. NmpJoinTimer = 0;
  357. }
  358. else {
  359. status = ERROR_CLUSTER_JOIN_ABORTED;
  360. ClRtlLogPrint(LOG_UNUSUAL,
  361. "[NMJOIN] CreateNetwork call for joining node %1!ws! "
  362. "failed because the join was aborted.\n",
  363. JoinerNodeId
  364. );
  365. }
  366. }
  367. else {
  368. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  369. ClRtlLogPrint(LOG_UNUSUAL,
  370. "[NMJOIN] CreateNetwork call for joining node %1!ws! "
  371. "failed because the node is not a member of the "
  372. "cluster.\n",
  373. JoinerNodeId
  374. );
  375. }
  376. }
  377. if (status == ERROR_SUCCESS) {
  378. status = NmpGlobalCreateNetwork(NetworkInfo, InterfaceInfo);
  379. if (joinerNode != NULL) {
  380. //
  381. // Verify that the join is still in progress
  382. //
  383. if ( (JoinSequence == NmpJoinSequence) &&
  384. (NmpJoinerNodeId == joinerNode->NodeId)
  385. )
  386. {
  387. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  388. CL_ASSERT(NmpJoinerUp == FALSE);
  389. CL_ASSERT(NmpSponsorNodeId == NmLocalNodeId);
  390. CL_ASSERT(NmpJoinTimer == 0);
  391. CL_ASSERT(NmpJoinAbortPending == FALSE);
  392. if (status == ERROR_SUCCESS) {
  393. //
  394. // Restart the join timer.
  395. //
  396. NmpJoinTimer = NM_JOIN_TIMEOUT;
  397. }
  398. else {
  399. //
  400. // Abort the join
  401. //
  402. NmpJoinAbort(status, joinerNode);
  403. }
  404. }
  405. else {
  406. status = ERROR_CLUSTER_JOIN_ABORTED;
  407. ClRtlLogPrint(LOG_UNUSUAL,
  408. "[NMJOIN] CreateNetwork call for joining node %1!ws! "
  409. "failed because the join was aborted.\n",
  410. JoinerNodeId
  411. );
  412. }
  413. }
  414. }
  415. if (joinerNode != NULL) {
  416. OmDereferenceObject(joinerNode);
  417. }
  418. NmpLockedLeaveApi();
  419. }
  420. else {
  421. status = ERROR_NODE_NOT_AVAILABLE;
  422. ClRtlLogPrint(LOG_NOISE,
  423. "[NMJOIN] Not in valid state to process CreateNetwork request.\n"
  424. );
  425. }
  426. NmpReleaseLock();
  427. return(status);
  428. } // s_NmRpcCreateNetwork2
  429. error_status_t
  430. s_NmRpcSetNetworkName(
  431. IN handle_t IDL_handle,
  432. IN DWORD JoinSequence, OPTIONAL
  433. IN LPWSTR JoinerNodeId, OPTIONAL
  434. IN PNM_NETWORK_INFO NetworkInfo
  435. )
  436. {
  437. DWORD status = ERROR_SUCCESS;
  438. ClRtlLogPrint(LOG_NOISE,
  439. "[NMJOIN] Received request to set name of network %1!ws! from "
  440. "joining node %2!ws!.\n",
  441. NetworkInfo->Id,
  442. JoinerNodeId
  443. );
  444. NmpAcquireLock();
  445. if (NmpLockedEnterApi(NmStateOnline)) {
  446. PNM_NODE joinerNode = NULL;
  447. if (lstrcmpW(JoinerNodeId, NmpInvalidJoinerIdString) != 0) {
  448. joinerNode = OmReferenceObjectById(
  449. ObjectTypeNode,
  450. JoinerNodeId
  451. );
  452. if (joinerNode != NULL) {
  453. if ( (JoinSequence == NmpJoinSequence) &&
  454. (NmpJoinerNodeId == joinerNode->NodeId) &&
  455. (NmpSponsorNodeId == NmLocalNodeId) &&
  456. !NmpJoinAbortPending
  457. )
  458. {
  459. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  460. CL_ASSERT(NmpJoinerUp == FALSE);
  461. CL_ASSERT(NmpJoinTimer != 0);
  462. //
  463. // Suspend the join timer while we are working on
  464. // behalf of the joiner. This precludes an abort
  465. // from occuring as well.
  466. //
  467. NmpJoinTimer = 0;
  468. }
  469. else {
  470. status = ERROR_CLUSTER_JOIN_ABORTED;
  471. ClRtlLogPrint(LOG_UNUSUAL,
  472. "[NMJOIN] SetNetworkName call for joining node "
  473. "%1!ws! failed because the join was aborted.\n",
  474. JoinerNodeId
  475. );
  476. }
  477. }
  478. else {
  479. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  480. ClRtlLogPrint(LOG_UNUSUAL,
  481. "[NMJOIN] SetNetworkName call for joining node %1!ws! "
  482. "failed because the node is not a member of the cluster.\n",
  483. JoinerNodeId
  484. );
  485. }
  486. }
  487. if (status == ERROR_SUCCESS) {
  488. status = NmpGlobalSetNetworkName( NetworkInfo );
  489. if (joinerNode != NULL) {
  490. //
  491. // Verify that the join is still in progress
  492. //
  493. if ( (JoinSequence == NmpJoinSequence) &&
  494. (NmpJoinerNodeId == joinerNode->NodeId)
  495. )
  496. {
  497. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  498. CL_ASSERT(NmpJoinerUp == FALSE);
  499. CL_ASSERT(NmpSponsorNodeId == NmLocalNodeId);
  500. CL_ASSERT(NmpJoinTimer == 0);
  501. CL_ASSERT(NmpJoinAbortPending == FALSE);
  502. if (status == ERROR_SUCCESS) {
  503. //
  504. // Restart the join timer.
  505. //
  506. NmpJoinTimer = NM_JOIN_TIMEOUT;
  507. }
  508. else {
  509. //
  510. // Abort the join
  511. //
  512. NmpJoinAbort(status, joinerNode);
  513. }
  514. }
  515. else {
  516. status = ERROR_CLUSTER_JOIN_ABORTED;
  517. ClRtlLogPrint(LOG_UNUSUAL,
  518. "[NMJOIN] SetNetworkName call for joining node "
  519. "%1!ws! failed because the join was aborted.\n",
  520. JoinerNodeId
  521. );
  522. }
  523. }
  524. }
  525. if (joinerNode != NULL) {
  526. OmDereferenceObject(joinerNode);
  527. }
  528. NmpLockedLeaveApi();
  529. }
  530. else {
  531. status = ERROR_NODE_NOT_AVAILABLE;
  532. ClRtlLogPrint(LOG_NOISE,
  533. "[NMJOIN] Not in valid state to process SetNetworkName request.\n"
  534. );
  535. }
  536. NmpReleaseLock();
  537. return(status);
  538. } // s_NmRpcSetNetworkName
  539. error_status_t
  540. s_NmRpcEnumNetworkDefinitions(
  541. IN handle_t IDL_handle,
  542. IN DWORD JoinSequence, OPTIONAL
  543. IN LPWSTR JoinerNodeId, OPTIONAL
  544. OUT PNM_NETWORK_ENUM * NetworkEnum
  545. )
  546. {
  547. DWORD status = ERROR_SUCCESS;
  548. PNM_NODE joinerNode = NULL;
  549. NmpAcquireLock();
  550. if (NmpLockedEnterApi(NmStateOnline)) {
  551. ClRtlLogPrint(LOG_NOISE,
  552. "[NMJOIN] Supplying network information to joining node.\n"
  553. );
  554. if (lstrcmpW(JoinerNodeId, NmpInvalidJoinerIdString) != 0) {
  555. joinerNode = OmReferenceObjectById(
  556. ObjectTypeNode,
  557. JoinerNodeId
  558. );
  559. if (joinerNode != NULL) {
  560. if ( (JoinSequence == NmpJoinSequence) &&
  561. (NmpJoinerNodeId == joinerNode->NodeId) &&
  562. (NmpSponsorNodeId == NmLocalNodeId) &&
  563. !NmpJoinAbortPending
  564. )
  565. {
  566. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  567. CL_ASSERT(NmpJoinerUp == FALSE);
  568. CL_ASSERT(NmpJoinTimer != 0);
  569. //
  570. // Suspend the join timer while we are working on
  571. // behalf of the joiner. This precludes an abort
  572. // from occuring as well.
  573. //
  574. NmpJoinTimer = 0;
  575. }
  576. else {
  577. status = ERROR_CLUSTER_JOIN_ABORTED;
  578. ClRtlLogPrint(LOG_UNUSUAL,
  579. "[NMJOIN] EnumNetworkDefinitions call for joining "
  580. "node %1!ws! failed because the join was aborted.\n",
  581. JoinerNodeId
  582. );
  583. }
  584. }
  585. else {
  586. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  587. ClRtlLogPrint(LOG_UNUSUAL,
  588. "[NMJOIN] EnumNetworkDefinitions call for joining "
  589. "node %1!ws! failed because the node is not a member "
  590. "of the cluster.\n",
  591. JoinerNodeId
  592. );
  593. }
  594. }
  595. if (status == ERROR_SUCCESS) {
  596. status = NmpEnumNetworkObjects(NetworkEnum);
  597. if (joinerNode != NULL) {
  598. if (status == ERROR_SUCCESS) {
  599. //
  600. // Restart the join timer.
  601. //
  602. NmpJoinTimer = NM_JOIN_TIMEOUT;
  603. }
  604. else {
  605. ClRtlLogPrint(LOG_CRITICAL,
  606. "[NMJOIN] Failed to enumerate network definitions, "
  607. "status %1!u!.\n",
  608. status
  609. );
  610. //
  611. // Abort the join
  612. //
  613. NmpJoinAbort(status, joinerNode);
  614. }
  615. }
  616. }
  617. if (joinerNode != NULL) {
  618. OmDereferenceObject(joinerNode);
  619. }
  620. NmpLockedLeaveApi();
  621. }
  622. else {
  623. status = ERROR_NODE_NOT_AVAILABLE;
  624. ClRtlLogPrint(LOG_NOISE,
  625. "[NMJOIN] Not in valid state to process EnumNetworkDefinitions "
  626. "request.\n"
  627. );
  628. }
  629. NmpReleaseLock();
  630. return(status);
  631. } // s_NmRpcEnumNetworkDefinitions
  632. error_status_t
  633. s_NmRpcEnumNetworkAndInterfaceStates(
  634. IN handle_t IDL_handle,
  635. IN DWORD JoinSequence,
  636. IN LPWSTR JoinerNodeId,
  637. OUT PNM_NETWORK_STATE_ENUM * NetworkStateEnum,
  638. OUT PNM_INTERFACE_STATE_ENUM * InterfaceStateEnum
  639. )
  640. {
  641. DWORD status = ERROR_SUCCESS;
  642. NmpAcquireLock();
  643. if (NmpLockedEnterApi(NmStateOnline)) {
  644. PNM_NODE joinerNode = OmReferenceObjectById(
  645. ObjectTypeNode,
  646. JoinerNodeId
  647. );
  648. ClRtlLogPrint(LOG_NOISE,
  649. "[NMJOIN] Supplying network and interface state information "
  650. "to joining node.\n"
  651. );
  652. if (joinerNode != NULL) {
  653. if ( (JoinSequence != NmpJoinSequence) ||
  654. (NmpJoinerNodeId != joinerNode->NodeId) ||
  655. (NmpSponsorNodeId != NmLocalNodeId) ||
  656. NmpJoinAbortPending
  657. )
  658. {
  659. status = ERROR_CLUSTER_JOIN_ABORTED;
  660. ClRtlLogPrint(LOG_UNUSUAL,
  661. "[NMJOIN] EnumNetworkAndInterfaceStates call for "
  662. "joining node %1!ws! failed because the join was "
  663. "aborted.\n",
  664. JoinerNodeId
  665. );
  666. }
  667. else {
  668. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  669. CL_ASSERT(NmpJoinerUp);
  670. CL_ASSERT(NmpJoinTimer == 0);
  671. }
  672. }
  673. else {
  674. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  675. ClRtlLogPrint(LOG_UNUSUAL,
  676. "[NMJOIN] EnumNetworkAndInterfaceStates call for joining "
  677. "node %1!ws! failed because the node is not a member of "
  678. "the cluster.\n",
  679. JoinerNodeId
  680. );
  681. }
  682. if (status == ERROR_SUCCESS) {
  683. status = NmpEnumNetworkObjectStates(NetworkStateEnum);
  684. if (status != ERROR_SUCCESS) {
  685. ClRtlLogPrint(LOG_CRITICAL,
  686. "[NMJOIN] EnumNetworkAndInterfaceStates failed, "
  687. "status %1!u!.\n",
  688. status
  689. );
  690. //
  691. // Abort the join
  692. //
  693. NmpJoinAbort(status, joinerNode);
  694. }
  695. status = NmpEnumInterfaceObjectStates(InterfaceStateEnum);
  696. if (status != ERROR_SUCCESS) {
  697. ClRtlLogPrint(LOG_CRITICAL,
  698. "[NMJOIN] EnumNetworkAndInterfaceStates failed, "
  699. "status %1!u!.\n",
  700. status
  701. );
  702. //
  703. // Abort the join
  704. //
  705. NmpJoinAbort(status, joinerNode);
  706. NmpFreeNetworkStateEnum(*NetworkStateEnum);
  707. *NetworkStateEnum = NULL;
  708. }
  709. }
  710. if (joinerNode != NULL) {
  711. OmDereferenceObject(joinerNode);
  712. }
  713. NmpLockedLeaveApi();
  714. }
  715. else {
  716. status = ERROR_NODE_NOT_AVAILABLE;
  717. ClRtlLogPrint(LOG_NOISE,
  718. "[NMJOIN] Not in valid state to process "
  719. "EnumNetworkAndInterfaceStates request.\n"
  720. );
  721. }
  722. NmpReleaseLock();
  723. return(status);
  724. } // s_NmRpcEnumNetworkAndInterfaceStates
  725. error_status_t
  726. s_NmRpcGetNetworkMulticastKey(
  727. IN PRPC_ASYNC_STATE AsyncState,
  728. IN handle_t IDL_handle,
  729. IN LPWSTR JoinerNodeId,
  730. IN LPWSTR NetworkId,
  731. OUT PNM_NETWORK_MULTICASTKEY * NetworkMulticastKey
  732. )
  733. {
  734. DWORD status = ERROR_SUCCESS;
  735. RPC_STATUS tempStatus;
  736. *NetworkMulticastKey = NULL;
  737. NmpAcquireLock();
  738. if (NmpLockedEnterApi(NmStateOnline))
  739. {
  740. PNM_NODE joinerNode;
  741. ClRtlLogPrint(LOG_NOISE,
  742. "[NMJOIN] Supplying multicast key for network %1!ws! "
  743. "to joining node %2!ws!.\n",
  744. NetworkId,
  745. JoinerNodeId
  746. );
  747. joinerNode = OmReferenceObjectById(ObjectTypeNode,
  748. JoinerNodeId
  749. );
  750. if (joinerNode == NULL) {
  751. ClRtlLogPrint(LOG_UNUSUAL,
  752. "[NMJOIN] s_NmRpcGetNetworkMulticastKey call for joining "
  753. "node %1!ws! failed because the node is not a member of "
  754. "the cluster.\n",
  755. JoinerNodeId
  756. );
  757. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  758. }
  759. else
  760. {
  761. status = NmpGetNetworkMulticastKey(NetworkId,
  762. NetworkMulticastKey);
  763. if (status != ERROR_SUCCESS)
  764. {
  765. ClRtlLogPrint(LOG_UNUSUAL,
  766. "[NMJOIN] NmpGetNetworkMulticastKey failed, "
  767. "status %1!u!.\n",
  768. status
  769. );
  770. }
  771. OmDereferenceObject(joinerNode);
  772. }
  773. NmpLockedLeaveApi();
  774. }
  775. else
  776. {
  777. ClRtlLogPrint(LOG_UNUSUAL,
  778. "[NMJOIN] Not in valid state to process "
  779. "NmRpcGetNetworkMulticastKey request.\n"
  780. );
  781. status = ERROR_NODE_NOT_AVAILABLE;
  782. }
  783. NmpReleaseLock();
  784. tempStatus = RpcAsyncCompleteCall(AsyncState, &status);
  785. if(tempStatus != RPC_S_OK)
  786. ClRtlLogPrint(LOG_UNUSUAL,
  787. "[NM] s_NmRpcGetNetworkMulticastKey, Error Completing "
  788. "Async RPC call, status %1!u!\n",
  789. tempStatus
  790. );
  791. return(status);
  792. } // s_NmRpcGetNetworkMulticastKey
  793. /////////////////////////////////////////////////////////////////////////////
  794. //
  795. // Routines used to make global configuration changes when the node
  796. // is online.
  797. //
  798. /////////////////////////////////////////////////////////////////////////////
  799. DWORD
  800. NmpGlobalCreateNetwork(
  801. IN PNM_NETWORK_INFO NetworkInfo,
  802. IN PNM_INTERFACE_INFO2 InterfaceInfo
  803. )
  804. /*++
  805. Notes:
  806. Called with the NmpLock held.
  807. --*/
  808. {
  809. DWORD status = ERROR_SUCCESS;
  810. DWORD networkPropertiesSize;
  811. PVOID networkProperties;
  812. ClRtlLogPrint(LOG_NOISE,
  813. "[NM] Issuing global update to create network %1!ws! and "
  814. "interface %2!ws!.\n",
  815. NetworkInfo->Id,
  816. InterfaceInfo->Id
  817. );
  818. //
  819. // Marshall the info structures into property lists.
  820. //
  821. status = NmpMarshallObjectInfo(
  822. NmpNetworkProperties,
  823. NetworkInfo,
  824. &networkProperties,
  825. &networkPropertiesSize
  826. );
  827. if (status == ERROR_SUCCESS) {
  828. DWORD interfacePropertiesSize;
  829. PVOID interfaceProperties;
  830. status = NmpMarshallObjectInfo(
  831. NmpInterfaceProperties,
  832. InterfaceInfo,
  833. &interfaceProperties,
  834. &interfacePropertiesSize
  835. );
  836. if (status == ERROR_SUCCESS) {
  837. NmpReleaseLock();
  838. //
  839. // Issue a global update to create the network
  840. //
  841. status = GumSendUpdateEx(
  842. GumUpdateMembership,
  843. NmUpdateCreateNetwork,
  844. 4,
  845. networkPropertiesSize,
  846. networkProperties,
  847. sizeof(networkPropertiesSize),
  848. &networkPropertiesSize,
  849. interfacePropertiesSize,
  850. interfaceProperties,
  851. sizeof(interfacePropertiesSize),
  852. &interfacePropertiesSize
  853. );
  854. if (status != ERROR_SUCCESS) {
  855. ClRtlLogPrint(LOG_CRITICAL,
  856. "[NM] Global update to create network %1!ws! failed, "
  857. "status %2!u!.\n",
  858. NetworkInfo->Id,
  859. status
  860. );
  861. }
  862. NmpAcquireLock();
  863. MIDL_user_free(interfaceProperties);
  864. }
  865. else {
  866. ClRtlLogPrint(LOG_CRITICAL,
  867. "[NM] Failed to marshall properties for new interface "
  868. "%1!ws!, status %2!u!\n",
  869. InterfaceInfo->Id,
  870. status
  871. );
  872. }
  873. MIDL_user_free(networkProperties);
  874. }
  875. else {
  876. ClRtlLogPrint(LOG_CRITICAL,
  877. "[NM] Failed to marshall properties for new network %1!ws!, "
  878. "status %2!u!\n",
  879. NetworkInfo->Id,
  880. status
  881. );
  882. }
  883. return(status);
  884. } // NmpGlobalCreateNetwork
  885. DWORD
  886. NmpGlobalSetNetworkName(
  887. IN PNM_NETWORK_INFO NetworkInfo
  888. )
  889. /*++
  890. Routine Description:
  891. Changes the name of a network defined for the cluster.
  892. Arguments:
  893. NetworkInfo - A pointer to info about the network to be modified.
  894. Return Value:
  895. ERROR_SUCCESS if the routine succeeds.
  896. A Win32 error code otherwise.
  897. Notes:
  898. Must not be called with NM lock held.
  899. --*/
  900. {
  901. DWORD status = ERROR_SUCCESS;
  902. if (status == ERROR_SUCCESS) {
  903. ClRtlLogPrint(LOG_NOISE,
  904. "[NM] Processing request to set name for network %1!ws! "
  905. "to '%2!ws!'.\n",
  906. NetworkInfo->Id,
  907. NetworkInfo->Name
  908. );
  909. //
  910. // Issue a global update
  911. //
  912. status = GumSendUpdateEx(
  913. GumUpdateMembership,
  914. NmUpdateSetNetworkName,
  915. 2,
  916. NM_WCSLEN(NetworkInfo->Id),
  917. NetworkInfo->Id,
  918. NM_WCSLEN( NetworkInfo->Name ),
  919. NetworkInfo->Name
  920. );
  921. if (status != ERROR_SUCCESS) {
  922. ClRtlLogPrint(LOG_CRITICAL,
  923. "[NM] Global update to set name of network %1!ws! "
  924. "failed, status %2!u!.\n",
  925. NetworkInfo->Id,
  926. status
  927. );
  928. }
  929. }
  930. else {
  931. ClRtlLogPrint(LOG_UNUSUAL,
  932. "[NM] New name parameter supplied for network %1!ws! is invalid\n",
  933. NetworkInfo->Id
  934. );
  935. }
  936. return(status);
  937. } // NmpGlobalSetNetworkName
  938. DWORD
  939. NmpGlobalSetNetworkAndInterfaceStates(
  940. PNM_NETWORK Network,
  941. CLUSTER_NETWORK_STATE NewNetworkState
  942. )
  943. /*++
  944. Notes:
  945. Called with NmpLock held and the Network referenced.
  946. --*/
  947. {
  948. DWORD status;
  949. DWORD i;
  950. LPCWSTR networkId = OmObjectId(Network);
  951. DWORD entryCount = Network->ConnectivityVector->EntryCount;
  952. DWORD vectorSize = sizeof(NM_STATE_ENTRY) * entryCount;
  953. PNM_STATE_ENTRY ifStateVector;
  954. ifStateVector = LocalAlloc(LMEM_FIXED, vectorSize);
  955. if (ifStateVector != NULL ) {
  956. for (i=0; i< entryCount; i++) {
  957. ifStateVector[i] = Network->StateWorkVector[i].State;
  958. }
  959. // DavidDio 8/16/2001
  960. // Bug 456951: Check the NmpGumUpdateHandlerRegistered flag
  961. // rather than the NmState to determine whether a GUM
  962. // update or a local routine should be used to set the
  963. // state.
  964. if (NmpGumUpdateHandlerRegistered) {
  965. //
  966. // Issue a global state update for this network.
  967. //
  968. NmpReleaseLock();
  969. status = GumSendUpdateEx(
  970. GumUpdateMembership,
  971. NmUpdateSetNetworkAndInterfaceStates,
  972. 4,
  973. NM_WCSLEN(networkId),
  974. networkId,
  975. sizeof(NewNetworkState),
  976. &NewNetworkState,
  977. vectorSize,
  978. ifStateVector,
  979. sizeof(entryCount),
  980. &entryCount
  981. );
  982. NmpAcquireLock();
  983. }
  984. else {
  985. CL_ASSERT(NmpState == NmStateOnlinePending);
  986. //
  987. // We're still in the form process. Bypass GUM.
  988. //
  989. NmpSetNetworkAndInterfaceStates(
  990. Network,
  991. NewNetworkState,
  992. ifStateVector,
  993. entryCount
  994. );
  995. status = ERROR_SUCCESS;
  996. }
  997. LocalFree(ifStateVector);
  998. }
  999. else {
  1000. status = ERROR_NOT_ENOUGH_MEMORY;
  1001. }
  1002. return(status);
  1003. } // NmpGlobalSetNetworkAndInterfaceStates
  1004. /////////////////////////////////////////////////////////////////////////////
  1005. //
  1006. // Routines called by other cluster service components
  1007. //
  1008. /////////////////////////////////////////////////////////////////////////////
  1009. CLUSTER_NETWORK_STATE
  1010. NmGetNetworkState(
  1011. IN PNM_NETWORK Network
  1012. )
  1013. /*++
  1014. Routine Description:
  1015. Arguments:
  1016. Return Value:
  1017. Notes:
  1018. Because the caller must have a reference on the object and the
  1019. call is so simple, there is no reason to put the call through the
  1020. EnterApi/LeaveApi dance.
  1021. --*/
  1022. {
  1023. CLUSTER_NETWORK_STATE state;
  1024. NmpAcquireLock();
  1025. state = Network->State;
  1026. NmpReleaseLock();
  1027. return(state);
  1028. } // NmGetNetworkState
  1029. DWORD
  1030. NmSetNetworkName(
  1031. IN PNM_NETWORK Network,
  1032. IN LPCWSTR Name
  1033. )
  1034. /*++
  1035. Routine Description:
  1036. Changes the name of a network defined for the cluster.
  1037. Arguments:
  1038. Network - A pointer to the object for the network to be modified.
  1039. Return Value:
  1040. ERROR_SUCCESS if the routine succeeds.
  1041. A Win32 error code otherwise.
  1042. Notes:
  1043. The network object must be referenced by the caller.
  1044. --*/
  1045. {
  1046. DWORD status = ERROR_SUCCESS;
  1047. if (NmpEnterApi(NmStateOnline)) {
  1048. LPCWSTR networkId = OmObjectId(Network);
  1049. DWORD nameLength;
  1050. //
  1051. // Validate the name
  1052. //
  1053. try {
  1054. nameLength = lstrlenW(Name);
  1055. if (nameLength == 0) {
  1056. status = ERROR_INVALID_PARAMETER;
  1057. }
  1058. }
  1059. except (EXCEPTION_EXECUTE_HANDLER) {
  1060. status = ERROR_INVALID_PARAMETER;
  1061. }
  1062. if (status == ERROR_SUCCESS) {
  1063. ClRtlLogPrint(LOG_NOISE,
  1064. "[NM] Processing request to set name for network %1!ws! "
  1065. "to %2!ws!.\n",
  1066. networkId,
  1067. Name
  1068. );
  1069. //
  1070. // Issue a global update
  1071. //
  1072. status = GumSendUpdateEx(
  1073. GumUpdateMembership,
  1074. NmUpdateSetNetworkName,
  1075. 2,
  1076. NM_WCSLEN(networkId),
  1077. networkId,
  1078. (nameLength + 1) * sizeof(WCHAR),
  1079. Name
  1080. );
  1081. if (status != ERROR_SUCCESS) {
  1082. ClRtlLogPrint(LOG_CRITICAL,
  1083. "[NM] Global update to set name of network %1!ws! "
  1084. "failed, status %2!u!.\n",
  1085. networkId,
  1086. status
  1087. );
  1088. }
  1089. }
  1090. else {
  1091. ClRtlLogPrint(LOG_UNUSUAL,
  1092. "[NM] New name parameter supplied for network %1!ws! "
  1093. "is invalid\n",
  1094. networkId
  1095. );
  1096. }
  1097. NmpLeaveApi();
  1098. }
  1099. else {
  1100. status = ERROR_NODE_NOT_AVAILABLE;
  1101. ClRtlLogPrint(LOG_NOISE,
  1102. "[NM] Not in valid state to process SetNetworkName request.\n"
  1103. );
  1104. }
  1105. return(status);
  1106. } // NmSetNetworkName
  1107. DWORD
  1108. NmSetNetworkPriorityOrder(
  1109. IN DWORD NetworkCount,
  1110. IN LPWSTR * NetworkIdList
  1111. )
  1112. /*++
  1113. Routine Description:
  1114. Sets the priority ordering of internal networks.
  1115. Arguments:
  1116. NetworkCount - Contains the count of items in NetworkIdList.
  1117. NetworkIdList - A pointer to an array of pointers to unicode strings.
  1118. Each string contains the ID of one internal network.
  1119. The array is sorted in priority order. The highest
  1120. priority network is listed first in the array.
  1121. Return Value:
  1122. ERROR_SUCCESS if the routine is successful.
  1123. A Win32 error code othewise.
  1124. --*/
  1125. {
  1126. DWORD status = ERROR_SUCCESS;
  1127. if (NetworkCount == 0) {
  1128. return(ERROR_INVALID_PARAMETER);
  1129. }
  1130. ClRtlLogPrint(LOG_NOISE,
  1131. "[NM] Received request to set network priority order.\n"
  1132. );
  1133. if (NmpEnterApi(NmStateOnline)) {
  1134. DWORD i;
  1135. DWORD multiSzLength = 0;
  1136. PVOID multiSz = NULL;
  1137. //
  1138. // Marshall the network ID list into a MULTI_SZ.
  1139. //
  1140. for (i=0; i< NetworkCount; i++) {
  1141. multiSzLength += NM_WCSLEN(NetworkIdList[i]);
  1142. }
  1143. multiSzLength += sizeof(UNICODE_NULL);
  1144. multiSz = MIDL_user_allocate(multiSzLength);
  1145. if (multiSz != NULL) {
  1146. LPWSTR tmp = multiSz;
  1147. for (i=0; i< NetworkCount; i++) {
  1148. lstrcpyW(tmp, NetworkIdList[i]);
  1149. tmp += lstrlenW(NetworkIdList[i]) + 1;
  1150. }
  1151. *tmp = UNICODE_NULL;
  1152. //
  1153. // Issue a global update
  1154. //
  1155. status = GumSendUpdateEx(
  1156. GumUpdateMembership,
  1157. NmUpdateSetNetworkPriorityOrder,
  1158. 1,
  1159. multiSzLength,
  1160. multiSz
  1161. );
  1162. if (status != ERROR_SUCCESS) {
  1163. ClRtlLogPrint(LOG_CRITICAL,
  1164. "[NM] Global update to reprioritize networks failed, "
  1165. "status %1!u!.\n",
  1166. status
  1167. );
  1168. }
  1169. MIDL_user_free(multiSz);
  1170. }
  1171. else {
  1172. status = ERROR_NOT_ENOUGH_MEMORY;
  1173. }
  1174. NmpLeaveApi();
  1175. }
  1176. else {
  1177. status = ERROR_NODE_NOT_AVAILABLE;
  1178. ClRtlLogPrint(LOG_NOISE,
  1179. "[NM] Not in valid state to process a request to set the "
  1180. "network priority order.\n"
  1181. );
  1182. }
  1183. return(status);
  1184. } // NmSetNetworkPriorityOrder
  1185. DWORD
  1186. NmEnumInternalNetworks(
  1187. OUT LPDWORD NetworkCount,
  1188. OUT PNM_NETWORK * NetworkList[]
  1189. )
  1190. /*++
  1191. Routine Description:
  1192. Returns a prioritized list of networks that are eligible to
  1193. carry internal communication.
  1194. Arguments:
  1195. NetworkCount - On output, contains the number of items in NetworkList.
  1196. NetworkList - On output, points to an array of pointers to network
  1197. objects. The highest priority network is first in the
  1198. array. Each pointer in the array must be dereferenced
  1199. by the caller. The storage for the array must be
  1200. deallocated by the caller.
  1201. Return Value:
  1202. ERROR_SUCCESS if the routine is successful.
  1203. A Win32 error code othewise.
  1204. --*/
  1205. {
  1206. DWORD status;
  1207. NmpAcquireLock();
  1208. if (NmpLockedEnterApi(NmStateOnline)) {
  1209. status = NmpEnumInternalNetworks(NetworkCount, NetworkList);
  1210. NmpLockedLeaveApi();
  1211. }
  1212. else {
  1213. status = ERROR_NODE_NOT_AVAILABLE;
  1214. ClRtlLogPrint(LOG_NOISE,
  1215. "[NM] Not in valid state to process EnumInternalNetworks "
  1216. "request.\n"
  1217. );
  1218. }
  1219. NmpReleaseLock();
  1220. return(status);
  1221. } // NmEnumInternalNetworks
  1222. DWORD
  1223. NmpEnumInternalNetworks(
  1224. OUT LPDWORD NetworkCount,
  1225. OUT PNM_NETWORK * NetworkList[]
  1226. )
  1227. /*++
  1228. Routine Description:
  1229. Returns a prioritized list of networks that are eligible to
  1230. carry internal communication.
  1231. Arguments:
  1232. NetworkCount - On output, contains the number of items in NetworkList.
  1233. NetworkList - On output, points to an array of pointers to network
  1234. objects. The highest priority network is first in the
  1235. array. Each pointer in the array must be dereferenced
  1236. by the caller. The storage for the array must be
  1237. deallocated by the caller.
  1238. Return Value:
  1239. ERROR_SUCCESS if the routine is successful.
  1240. A Win32 error code othewise.
  1241. Notes:
  1242. Called with NM Lock held.
  1243. --*/
  1244. {
  1245. DWORD status = ERROR_SUCCESS;
  1246. if (NmpInternalNetworkCount > 0) {
  1247. PNM_NETWORK * networkList = LocalAlloc(
  1248. LMEM_FIXED,
  1249. ( sizeof(PNM_NETWORK) *
  1250. NmpInternalNetworkCount)
  1251. );
  1252. if (networkList != NULL) {
  1253. PNM_NETWORK network;
  1254. PLIST_ENTRY entry;
  1255. DWORD networkCount = 0;
  1256. //
  1257. // The internal network list is sorted in priority order.
  1258. // The highest priority network is at the head of the list.
  1259. //
  1260. for (entry = NmpInternalNetworkList.Flink;
  1261. entry != &NmpInternalNetworkList;
  1262. entry = entry->Flink
  1263. )
  1264. {
  1265. network = CONTAINING_RECORD(
  1266. entry,
  1267. NM_NETWORK,
  1268. InternalLinkage
  1269. );
  1270. CL_ASSERT(NmpIsNetworkForInternalUse(network));
  1271. OmReferenceObject(network);
  1272. networkList[networkCount++] = network;
  1273. }
  1274. CL_ASSERT(networkCount == NmpInternalNetworkCount);
  1275. *NetworkCount = networkCount;
  1276. *NetworkList = networkList;
  1277. }
  1278. else {
  1279. status = ERROR_NOT_ENOUGH_MEMORY;
  1280. }
  1281. }
  1282. else {
  1283. *NetworkCount = 0;
  1284. *NetworkList = NULL;
  1285. }
  1286. return(status);
  1287. } // NmpEnumInternalNetworks
  1288. DWORD
  1289. NmEnumNetworkInterfaces(
  1290. IN PNM_NETWORK Network,
  1291. OUT LPDWORD InterfaceCount,
  1292. OUT PNM_INTERFACE * InterfaceList[]
  1293. )
  1294. /*++
  1295. Routine Description:
  1296. Returns the list of interfaces associated with a specified network.
  1297. Arguments:
  1298. Network - A pointer to the network object for which to enumerate
  1299. interfaces.
  1300. InterfaceCount - On output, contains the number of items in InterfaceList.
  1301. InterfaceList - On output, points to an array of pointers to interface
  1302. objects. Each pointer in the array must be dereferenced
  1303. by the caller. The storage for the array must be
  1304. deallocated by the caller.
  1305. Return Value:
  1306. ERROR_SUCCESS if the routine is successful.
  1307. A Win32 error code othewise.
  1308. --*/
  1309. {
  1310. DWORD status = ERROR_SUCCESS;
  1311. NmpAcquireLock();
  1312. if (NmpLockedEnterApi(NmStateOnline)) {
  1313. if (Network->InterfaceCount > 0) {
  1314. PNM_INTERFACE * interfaceList = LocalAlloc(
  1315. LMEM_FIXED,
  1316. ( sizeof(PNM_INTERFACE) *
  1317. Network->InterfaceCount)
  1318. );
  1319. if (interfaceList != NULL) {
  1320. PNM_INTERFACE netInterface;
  1321. PLIST_ENTRY entry;
  1322. DWORD i;
  1323. for (entry = Network->InterfaceList.Flink, i=0;
  1324. entry != &(Network->InterfaceList);
  1325. entry = entry->Flink, i++
  1326. )
  1327. {
  1328. netInterface = CONTAINING_RECORD(
  1329. entry,
  1330. NM_INTERFACE,
  1331. NetworkLinkage
  1332. );
  1333. OmReferenceObject(netInterface);
  1334. interfaceList[i] = netInterface;
  1335. }
  1336. *InterfaceCount = Network->InterfaceCount;
  1337. *InterfaceList = interfaceList;
  1338. }
  1339. else {
  1340. status = ERROR_NOT_ENOUGH_MEMORY;
  1341. }
  1342. }
  1343. else {
  1344. *InterfaceCount = 0;
  1345. *InterfaceList = NULL;
  1346. }
  1347. NmpLockedLeaveApi();
  1348. }
  1349. else {
  1350. status = ERROR_NODE_NOT_AVAILABLE;
  1351. ClRtlLogPrint(LOG_UNUSUAL,
  1352. "[NM] Not in valid state to process EnumNetworkInterfaces "
  1353. "request.\n"
  1354. );
  1355. }
  1356. NmpReleaseLock();
  1357. return(status);
  1358. } // NmEnumNetworkInterfaces
  1359. /////////////////////////////////////////////////////////////////////////////
  1360. //
  1361. // Handlers for global updates
  1362. //
  1363. /////////////////////////////////////////////////////////////////////////////
  1364. DWORD
  1365. NmpUpdateCreateNetwork(
  1366. IN BOOL IsSourceNode,
  1367. IN PVOID NetworkPropertyList,
  1368. IN LPDWORD NetworkPropertyListSize,
  1369. IN PVOID InterfacePropertyList,
  1370. IN LPDWORD InterfacePropertyListSize
  1371. )
  1372. /*++
  1373. Routine Description:
  1374. Global update handler for creating a new network. The network
  1375. definition is read from the cluster database, and a corresponding
  1376. object is instantiated. The cluster transport is also updated if
  1377. necessary.
  1378. Arguments:
  1379. IsSourceNode - Set to TRUE if this node is the source of the update.
  1380. Set to FALSE otherwise.
  1381. Return Value:
  1382. ERROR_SUCCESS if the routine succeeds.
  1383. A Win32 error code otherwise.
  1384. Notes:
  1385. This routine must not be called with NM lock held.
  1386. --*/
  1387. {
  1388. DWORD status;
  1389. NM_NETWORK_INFO networkInfo;
  1390. NM_INTERFACE_INFO2 interfaceInfo;
  1391. PNM_NETWORK network = NULL;
  1392. PNM_INTERFACE netInterface = NULL;
  1393. HLOCALXSACTION xaction = NULL;
  1394. BOOLEAN isInternalNetwork = FALSE;
  1395. BOOLEAN isLockAcquired = FALSE;
  1396. CL_NODE_ID joinerNodeId;
  1397. if (!NmpEnterApi(NmStateOnline)) {
  1398. ClRtlLogPrint(LOG_NOISE,
  1399. "[NM] Not in valid state to process CreateNetwork update.\n"
  1400. );
  1401. return(ERROR_NODE_NOT_AVAILABLE);
  1402. }
  1403. //
  1404. // Unmarshall the property lists.
  1405. //
  1406. ZeroMemory(&networkInfo, sizeof(networkInfo));
  1407. ZeroMemory(&interfaceInfo, sizeof(interfaceInfo));
  1408. status = ClRtlVerifyPropertyTable(
  1409. NmpNetworkProperties,
  1410. NULL, // Reserved
  1411. FALSE, // Don't allow unknowns
  1412. NetworkPropertyList,
  1413. *NetworkPropertyListSize,
  1414. (LPBYTE) &networkInfo
  1415. );
  1416. if ( status != ERROR_SUCCESS ) {
  1417. ClRtlLogPrint( LOG_CRITICAL,
  1418. "[NM] Failed to unmarshall properties for new network, "
  1419. "status %1!u!.\n",
  1420. status
  1421. );
  1422. goto error_exit;
  1423. }
  1424. status = ClRtlVerifyPropertyTable(
  1425. NmpInterfaceProperties,
  1426. NULL, // Reserved
  1427. FALSE, // Don't allow unknowns
  1428. InterfacePropertyList,
  1429. *InterfacePropertyListSize,
  1430. (LPBYTE) &interfaceInfo
  1431. );
  1432. if ( status != ERROR_SUCCESS ) {
  1433. ClRtlLogPrint( LOG_CRITICAL,
  1434. "[NM] Failed to unmarshall properties for new interface, "
  1435. "status %1!u!.\n",
  1436. status
  1437. );
  1438. goto error_exit;
  1439. }
  1440. ClRtlLogPrint(LOG_NOISE,
  1441. "[NM] Received update to create network %1!ws! & interface %2!ws!.\n",
  1442. networkInfo.Id,
  1443. interfaceInfo.Id
  1444. );
  1445. //
  1446. // Start a transaction - this must be done before acquiring the NM lock.
  1447. //
  1448. xaction = DmBeginLocalUpdate();
  1449. if (xaction == NULL) {
  1450. status = GetLastError();
  1451. ClRtlLogPrint(LOG_CRITICAL,
  1452. "[NM] Failed to begin a transaction, status %1!u!\n",
  1453. status
  1454. );
  1455. goto error_exit;
  1456. }
  1457. NmpAcquireLock(); isLockAcquired = TRUE;
  1458. //
  1459. // Fix up the network's priority, if needed.
  1460. //
  1461. if (networkInfo.Role & ClusterNetworkRoleInternalUse) {
  1462. CL_ASSERT(networkInfo.Priority == 0xFFFFFFFF);
  1463. //
  1464. // The network's priority is one greater than that of the lowest
  1465. // priority network already in the internal network list.
  1466. //
  1467. if (IsListEmpty(&NmpInternalNetworkList)) {
  1468. networkInfo.Priority = 1;
  1469. }
  1470. else {
  1471. PNM_NETWORK lastnet = CONTAINING_RECORD(
  1472. NmpInternalNetworkList.Blink,
  1473. NM_NETWORK,
  1474. InternalLinkage
  1475. );
  1476. CL_ASSERT(lastnet->Priority != 0);
  1477. CL_ASSERT(lastnet->Priority != 0xFFFFFFFF);
  1478. networkInfo.Priority = lastnet->Priority + 1;
  1479. }
  1480. isInternalNetwork = TRUE;
  1481. }
  1482. //
  1483. // Update the database.
  1484. //
  1485. status = NmpCreateNetworkDefinition(&networkInfo, xaction);
  1486. if (status != ERROR_SUCCESS) {
  1487. goto error_exit;
  1488. }
  1489. status = NmpCreateInterfaceDefinition(&interfaceInfo, xaction);
  1490. if (status != ERROR_SUCCESS) {
  1491. goto error_exit;
  1492. }
  1493. joinerNodeId = NmpJoinerNodeId;
  1494. NmpReleaseLock(); isLockAcquired = FALSE;
  1495. network = NmpCreateNetworkObject(&networkInfo);
  1496. if (network == NULL) {
  1497. status = GetLastError();
  1498. ClRtlLogPrint(LOG_CRITICAL,
  1499. "[NM] Failed to create object for network %1!ws!, "
  1500. "status %2!u!.\n",
  1501. networkInfo.Id,
  1502. status
  1503. );
  1504. goto error_exit;
  1505. }
  1506. netInterface = NmpCreateInterfaceObject(
  1507. &interfaceInfo,
  1508. TRUE // Do retry on failure
  1509. );
  1510. #ifdef CLUSTER_TESTPOINT
  1511. TESTPT(TpFailNmCreateNetwork) {
  1512. NmpAcquireLock();
  1513. NmpDeleteInterfaceObject(netInterface, FALSE); netInterface = NULL;
  1514. NmpReleaseLock();
  1515. SetLastError(999999);
  1516. }
  1517. #endif
  1518. NmpAcquireLock(); isLockAcquired = TRUE;
  1519. if (netInterface == NULL) {
  1520. status = GetLastError();
  1521. ClRtlLogPrint(LOG_CRITICAL,
  1522. "[NM] Failed to create object for interface %1!ws!, "
  1523. "status %2!u!.\n",
  1524. interfaceInfo.Id,
  1525. status
  1526. );
  1527. NmpDeleteNetworkObject(network, FALSE);
  1528. OmDereferenceObject(network);
  1529. goto error_exit;
  1530. }
  1531. //
  1532. // If a node happens to be joining right now, flag the fact that
  1533. // it is now out of synch with the cluster config.
  1534. //
  1535. if ( ( (joinerNodeId != ClusterInvalidNodeId) &&
  1536. (netInterface->Node->NodeId != joinerNodeId)
  1537. ) ||
  1538. ( (NmpJoinerNodeId != ClusterInvalidNodeId) &&
  1539. (netInterface->Node->NodeId != NmpJoinerNodeId)
  1540. )
  1541. )
  1542. {
  1543. NmpJoinerOutOfSynch = TRUE;
  1544. }
  1545. ClusterEvent(CLUSTER_EVENT_NETWORK_ADDED, network);
  1546. ClusterEvent(CLUSTER_EVENT_NETINTERFACE_ADDED, netInterface);
  1547. if (isInternalNetwork) {
  1548. NmpIssueClusterPropertyChangeEvent();
  1549. }
  1550. OmDereferenceObject(netInterface);
  1551. OmDereferenceObject(network);
  1552. CL_ASSERT(status == ERROR_SUCCESS);
  1553. error_exit:
  1554. if (isLockAcquired) {
  1555. NmpLockedLeaveApi();
  1556. NmpReleaseLock();
  1557. }
  1558. else {
  1559. NmpLeaveApi();
  1560. }
  1561. if (xaction != NULL) {
  1562. //
  1563. // Complete the transaction - this must be done after releasing
  1564. // the NM lock.
  1565. //
  1566. if (status == ERROR_SUCCESS) {
  1567. DmCommitLocalUpdate(xaction);
  1568. }
  1569. else {
  1570. DmAbortLocalUpdate(xaction);
  1571. }
  1572. }
  1573. ClNetFreeNetworkInfo(&networkInfo);
  1574. ClNetFreeInterfaceInfo(&interfaceInfo);
  1575. return(status);
  1576. } // NmpUpdateCreateNetwork
  1577. DWORD
  1578. NmpUpdateSetNetworkName(
  1579. IN BOOL IsSourceNode,
  1580. IN LPWSTR NetworkId,
  1581. IN LPWSTR NewNetworkName
  1582. )
  1583. /*++
  1584. Routine Description:
  1585. Global update handler for setting the name of a network.
  1586. Arguments:
  1587. IsSourceNode - Set to TRUE if this node is the source of the update.
  1588. Set to FALSE otherwise.
  1589. NetworkId - A pointer to a unicode string containing the ID of the
  1590. network to update.
  1591. NewNetworkName - A pointer to a unicode string containing the new network name.
  1592. Return Value:
  1593. ERROR_SUCCESS if the routine succeeds.
  1594. A Win32 error code otherwise.
  1595. Notes:
  1596. This routine must not be called with NM lock held.
  1597. --*/
  1598. {
  1599. DWORD status;
  1600. DWORD i;
  1601. PLIST_ENTRY entry;
  1602. HLOCALXSACTION xaction = NULL;
  1603. HDMKEY networkKey;
  1604. HDMKEY netInterfaceKey;
  1605. PNM_NETWORK network = NULL;
  1606. PNM_INTERFACE netInterface;
  1607. LPCWSTR netInterfaceId;
  1608. LPCWSTR netInterfaceName;
  1609. LPCWSTR networkName;
  1610. LPCWSTR nodeName;
  1611. LPWSTR oldNetworkName = NULL;
  1612. LPWSTR * oldNameVector = NULL;
  1613. LPWSTR * newNameVector = NULL;
  1614. BOOLEAN isLockAcquired = FALSE;
  1615. DWORD interfaceCount;
  1616. if (!NmpEnterApi(NmStateOnline)) {
  1617. ClRtlLogPrint(LOG_NOISE,
  1618. "[NM] Not in valid state to process SetNetworkName update.\n"
  1619. );
  1620. return(ERROR_NODE_NOT_AVAILABLE);
  1621. }
  1622. ClRtlLogPrint(LOG_NOISE,
  1623. "[NM] Received update to set the name for network %1!ws! "
  1624. "to '%2!ws!'.\n",
  1625. NetworkId,
  1626. NewNetworkName
  1627. );
  1628. //
  1629. // Find the network's object
  1630. //
  1631. network = OmReferenceObjectById(ObjectTypeNetwork, NetworkId);
  1632. if (network == NULL) {
  1633. ClRtlLogPrint(LOG_CRITICAL,
  1634. "[NM] Unable to find network %1!ws!.\n",
  1635. NetworkId
  1636. );
  1637. status = ERROR_CLUSTER_NETWORK_NOT_FOUND;
  1638. goto error_exit;
  1639. }
  1640. //
  1641. // Start a transaction - this must be done before acquiring the NM lock.
  1642. //
  1643. xaction = DmBeginLocalUpdate();
  1644. if (xaction == NULL) {
  1645. status = GetLastError();
  1646. ClRtlLogPrint(LOG_CRITICAL,
  1647. "[NM] Failed to begin a transaction, status %1!u!\n",
  1648. status
  1649. );
  1650. goto error_exit;
  1651. }
  1652. NmpAcquireLock(); isLockAcquired = TRUE;
  1653. //
  1654. // compare the names. If the same, return success
  1655. //
  1656. if ( ClRtlStrICmp( OmObjectName( network ), NewNetworkName ) == 0 ) {
  1657. ClRtlLogPrint(LOG_NOISE, "[NM] Network name does not need changing.\n");
  1658. status = ERROR_SUCCESS;
  1659. goto error_exit;
  1660. }
  1661. networkName = OmObjectName(network);
  1662. oldNetworkName = LocalAlloc(LMEM_FIXED, NM_WCSLEN(networkName));
  1663. if (oldNetworkName == NULL) {
  1664. ClRtlLogPrint(LOG_CRITICAL,
  1665. "[NM] Failed to allocate memory for network %1!ws! name change!\n",
  1666. NetworkId
  1667. );
  1668. status = ERROR_NOT_ENOUGH_MEMORY;
  1669. goto error_exit;
  1670. }
  1671. wcscpy(oldNetworkName, networkName);
  1672. //
  1673. // Update the database.
  1674. //
  1675. // This processing can always be undone on error.
  1676. //
  1677. networkKey = DmOpenKey(DmNetworksKey, NetworkId, KEY_WRITE);
  1678. if (networkKey == NULL) {
  1679. status = GetLastError();
  1680. ClRtlLogPrint(LOG_CRITICAL,
  1681. "[NM] Failed to open database key for network %1!ws!, "
  1682. "status %2!u!\n",
  1683. NetworkId,
  1684. status
  1685. );
  1686. goto error_exit;
  1687. }
  1688. status = DmLocalSetValue(
  1689. xaction,
  1690. networkKey,
  1691. CLUSREG_NAME_NET_NAME,
  1692. REG_SZ,
  1693. (CONST BYTE *) NewNetworkName,
  1694. NM_WCSLEN(NewNetworkName)
  1695. );
  1696. DmCloseKey(networkKey);
  1697. if (status != ERROR_SUCCESS) {
  1698. ClRtlLogPrint(LOG_CRITICAL,
  1699. "[NM] Set of name value failed for network %1!ws!, "
  1700. "status %2!u!.\n",
  1701. NetworkId,
  1702. status
  1703. );
  1704. goto error_exit;
  1705. }
  1706. //
  1707. // Update the names of all of the interfaces on this network
  1708. //
  1709. interfaceCount = network->InterfaceCount;
  1710. oldNameVector = LocalAlloc(
  1711. LMEM_FIXED | LMEM_ZEROINIT,
  1712. interfaceCount * sizeof(LPWSTR)
  1713. );
  1714. newNameVector = LocalAlloc(
  1715. LMEM_FIXED | LMEM_ZEROINIT,
  1716. interfaceCount * sizeof(LPWSTR)
  1717. );
  1718. if ((oldNameVector == NULL) || (newNameVector == NULL)) {
  1719. ClRtlLogPrint(LOG_CRITICAL,
  1720. "[NM] Failed to allocate memory for net interface name change.\n"
  1721. );
  1722. goto error_exit;
  1723. }
  1724. for (entry = network->InterfaceList.Flink, i = 0;
  1725. entry != &(network->InterfaceList);
  1726. entry = entry->Flink, i++
  1727. )
  1728. {
  1729. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, NetworkLinkage);
  1730. netInterfaceId = OmObjectId(netInterface);
  1731. netInterfaceName = OmObjectName(netInterface);
  1732. nodeName = OmObjectName(netInterface->Node);
  1733. oldNameVector[i] = LocalAlloc(
  1734. LMEM_FIXED,
  1735. NM_WCSLEN(netInterfaceName)
  1736. );
  1737. newNameVector[i] = ClNetMakeInterfaceName(
  1738. NULL,
  1739. (LPWSTR) nodeName,
  1740. NewNetworkName
  1741. );
  1742. if ((oldNameVector[i] == NULL) || (newNameVector[i] == NULL)) {
  1743. ClRtlLogPrint(LOG_CRITICAL,
  1744. "[NM] Failed to allocate memory for net interface name "
  1745. "change.\n"
  1746. );
  1747. goto error_exit;
  1748. }
  1749. wcscpy(oldNameVector[i], netInterfaceName);
  1750. netInterfaceKey = DmOpenKey(
  1751. DmNetInterfacesKey,
  1752. netInterfaceId,
  1753. KEY_WRITE
  1754. );
  1755. if (netInterfaceKey == NULL) {
  1756. status = GetLastError();
  1757. ClRtlLogPrint(LOG_CRITICAL,
  1758. "[NM] Failed to open database key for net interface "
  1759. "%1!ws!, status %2!u!\n",
  1760. netInterfaceId,
  1761. status
  1762. );
  1763. goto error_exit;
  1764. }
  1765. status = DmLocalSetValue(
  1766. xaction,
  1767. netInterfaceKey,
  1768. CLUSREG_NAME_NETIFACE_NAME,
  1769. REG_SZ,
  1770. (CONST BYTE *) newNameVector[i],
  1771. NM_WCSLEN(newNameVector[i])
  1772. );
  1773. DmCloseKey(netInterfaceKey);
  1774. if (status != ERROR_SUCCESS) {
  1775. ClRtlLogPrint(LOG_CRITICAL,
  1776. "[NM] Set of name value failed for net interface %1!ws!, "
  1777. "status %2!u!.\n",
  1778. netInterfaceId,
  1779. status
  1780. );
  1781. goto error_exit;
  1782. }
  1783. }
  1784. //
  1785. // Update the in-memory objects.
  1786. //
  1787. // This processing may not be undoable on error.
  1788. //
  1789. //
  1790. // Update name of the network
  1791. //
  1792. status = OmSetObjectName(network, NewNetworkName);
  1793. if (status != ERROR_SUCCESS) {
  1794. ClRtlLogPrint(LOG_CRITICAL,
  1795. "[NM] Failed to change name for network %1!ws!, status %2!u!\n",
  1796. NetworkId,
  1797. status
  1798. );
  1799. goto error_exit;
  1800. }
  1801. //
  1802. // Update the names of all of the interfaces on the network.
  1803. //
  1804. for (entry = network->InterfaceList.Flink, i = 0;
  1805. entry != &(network->InterfaceList);
  1806. entry = entry->Flink, i++
  1807. )
  1808. {
  1809. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, NetworkLinkage);
  1810. netInterfaceId = OmObjectId(netInterface);
  1811. status = OmSetObjectName(netInterface, newNameVector[i]);
  1812. if (status != ERROR_SUCCESS) {
  1813. //
  1814. // Try to undo what has already been done. If we fail, we must
  1815. // commit suicide to preserve consistency.
  1816. //
  1817. DWORD j;
  1818. PLIST_ENTRY entry2;
  1819. DWORD undoStatus;
  1820. ClRtlLogPrint(LOG_CRITICAL,
  1821. "[NM] Failed to change name for net interface %1!ws!, "
  1822. "status %2!u!\n",
  1823. netInterfaceId,
  1824. status
  1825. );
  1826. //
  1827. // Undo the update of the network name
  1828. //
  1829. undoStatus = OmSetObjectName(network, oldNetworkName);
  1830. if (undoStatus != ERROR_SUCCESS) {
  1831. ClRtlLogPrint(LOG_CRITICAL,
  1832. "[NM] Failed to undo change of name for network %1!ws!, "
  1833. "status %2!u!\n",
  1834. NetworkId,
  1835. undoStatus
  1836. );
  1837. CsInconsistencyHalt(undoStatus);
  1838. }
  1839. //
  1840. // Undo update of network interface names
  1841. //
  1842. for (j = 0, entry2 = network->InterfaceList.Flink;
  1843. j < i;
  1844. j++, entry2 = entry2->Flink
  1845. )
  1846. {
  1847. netInterface = CONTAINING_RECORD(
  1848. entry2,
  1849. NM_INTERFACE,
  1850. NetworkLinkage
  1851. );
  1852. netInterfaceId = OmObjectId(netInterface);
  1853. undoStatus = OmSetObjectName(netInterface, oldNameVector[i]);
  1854. if (undoStatus != ERROR_SUCCESS) {
  1855. ClRtlLogPrint(LOG_CRITICAL,
  1856. "[NM] Failed to undo change of name for net "
  1857. "interface %1!ws!, status %2!u!\n",
  1858. netInterfaceId,
  1859. undoStatus
  1860. );
  1861. CsInconsistencyHalt(undoStatus);
  1862. }
  1863. }
  1864. goto error_exit;
  1865. }
  1866. }
  1867. //
  1868. // Set the corresponding connectoid object name if necessary.
  1869. //
  1870. if (network->LocalInterface != NULL) {
  1871. INetConnection * connectoid;
  1872. LPWSTR connectoidName;
  1873. DWORD tempStatus;
  1874. connectoid = ClRtlFindConnectoidByGuid(
  1875. network->LocalInterface->AdapterId
  1876. );
  1877. if (connectoid != NULL) {
  1878. connectoidName = ClRtlGetConnectoidName(connectoid);
  1879. if (connectoidName != NULL) {
  1880. if (lstrcmpW(connectoidName, NewNetworkName) != 0) {
  1881. tempStatus = ClRtlSetConnectoidName(
  1882. connectoid,
  1883. NewNetworkName
  1884. );
  1885. if (tempStatus != ERROR_SUCCESS) {
  1886. ClRtlLogPrint(LOG_UNUSUAL,
  1887. "[NM] Failed to set name of Network Connection "
  1888. "Object for interface on cluster network %1!ws! "
  1889. "(%2!ws!), status %3!u!\n",
  1890. oldNetworkName,
  1891. NetworkId,
  1892. tempStatus
  1893. );
  1894. } else {
  1895. // We expect to see a callback from the Network
  1896. // Connection Object with the name we just set.
  1897. // To avoid endless feedback loops, we need to
  1898. // ignore any other Network Connection Object
  1899. // callbacks until that one.
  1900. network->Flags |= NM_FLAG_NET_NAME_CHANGE_PENDING;
  1901. // We don't want to absolutely rely on the callback
  1902. // from the Network Connection Object, so we will
  1903. // set a timeout to clear the flag.
  1904. NmpStartNetworkNameChangePendingTimer(
  1905. network,
  1906. NM_NET_NAME_CHANGE_PENDING_TIMEOUT
  1907. );
  1908. }
  1909. }
  1910. }
  1911. else {
  1912. tempStatus = GetLastError();
  1913. ClRtlLogPrint(LOG_UNUSUAL,
  1914. "[NM] Failed to query name of Network Connection Object "
  1915. "for interface on cluster network %1!ws! (%2!ws!), "
  1916. "status %3!u!\n",
  1917. oldNetworkName,
  1918. NetworkId,
  1919. tempStatus
  1920. );
  1921. }
  1922. INetConnection_Release( connectoid );
  1923. }
  1924. else {
  1925. tempStatus = GetLastError();
  1926. ClRtlLogPrint(LOG_UNUSUAL,
  1927. "[NM] Failed to find Network Connection Object for "
  1928. "interface on cluster network %1!ws! (%2!ws!), "
  1929. "status %3!u!\n",
  1930. oldNetworkName,
  1931. NetworkId,
  1932. tempStatus
  1933. );
  1934. }
  1935. }
  1936. //
  1937. // Issue property change events.
  1938. //
  1939. ClusterEvent(CLUSTER_EVENT_NETWORK_PROPERTY_CHANGE, network);
  1940. for (entry = network->InterfaceList.Flink;
  1941. entry != &(network->InterfaceList);
  1942. entry = entry->Flink
  1943. )
  1944. {
  1945. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, NetworkLinkage);
  1946. ClusterEvent(
  1947. CLUSTER_EVENT_NETINTERFACE_PROPERTY_CHANGE,
  1948. netInterface
  1949. );
  1950. }
  1951. CL_ASSERT(status == ERROR_SUCCESS);
  1952. error_exit:
  1953. if (isLockAcquired) {
  1954. NmpLockedLeaveApi();
  1955. NmpReleaseLock();
  1956. }
  1957. else {
  1958. NmpLeaveApi();
  1959. }
  1960. if (xaction != NULL) {
  1961. //
  1962. // Complete the transaction - this must be done after releasing
  1963. // the NM lock.
  1964. //
  1965. if (status == ERROR_SUCCESS) {
  1966. DmCommitLocalUpdate(xaction);
  1967. }
  1968. else {
  1969. DmAbortLocalUpdate(xaction);
  1970. }
  1971. }
  1972. if (network != NULL) {
  1973. OmDereferenceObject(network);
  1974. if (oldNetworkName != NULL) {
  1975. LocalFree(oldNetworkName);
  1976. }
  1977. if (oldNameVector != NULL) {
  1978. for (i=0; i < interfaceCount; i++) {
  1979. if (oldNameVector[i] == NULL) {
  1980. break;
  1981. }
  1982. LocalFree(oldNameVector[i]);
  1983. }
  1984. LocalFree(oldNameVector);
  1985. }
  1986. if (newNameVector != NULL) {
  1987. for (i=0; i < interfaceCount; i++) {
  1988. if (newNameVector[i] == NULL) {
  1989. break;
  1990. }
  1991. LocalFree(newNameVector[i]);
  1992. }
  1993. LocalFree(newNameVector);
  1994. }
  1995. }
  1996. return(status);
  1997. } // NmpUpdateSetNetworkName
  1998. DWORD
  1999. NmpUpdateSetNetworkPriorityOrder(
  2000. IN BOOL IsSourceNode,
  2001. IN LPCWSTR NetworkIdList
  2002. )
  2003. {
  2004. DWORD status = ERROR_SUCCESS;
  2005. PNM_NETWORK network;
  2006. PLIST_ENTRY entry;
  2007. DWORD matchCount=0;
  2008. DWORD networkCount=0;
  2009. PNM_NETWORK * networkList=NULL;
  2010. DWORD i;
  2011. DWORD multiSzLength;
  2012. LPCWSTR networkId;
  2013. HLOCALXSACTION xaction = NULL;
  2014. BOOLEAN isLockAcquired = FALSE;
  2015. if (!NmpEnterApi(NmStateOnline)) {
  2016. ClRtlLogPrint(LOG_NOISE,
  2017. "[NM] Not in valid state to process SetNetworkPriorityOrder "
  2018. "update.\n"
  2019. );
  2020. return(ERROR_NODE_NOT_AVAILABLE);
  2021. }
  2022. ClRtlLogPrint(LOG_NOISE,
  2023. "[NM] Received update to set network priority order.\n"
  2024. );
  2025. //
  2026. // Unmarshall the MULTI_SZ
  2027. //
  2028. try {
  2029. multiSzLength = ClRtlMultiSzLength(NetworkIdList);
  2030. for (i=0; ; i++) {
  2031. networkId = ClRtlMultiSzEnum(
  2032. NetworkIdList,
  2033. multiSzLength,
  2034. i
  2035. );
  2036. if (networkId == NULL) {
  2037. break;
  2038. }
  2039. networkCount++;
  2040. }
  2041. }
  2042. except(EXCEPTION_EXECUTE_HANDLER) {
  2043. ClRtlLogPrint(LOG_UNUSUAL,
  2044. "[NM] Hit exception while parsing network ID list for "
  2045. "priority change\n"
  2046. );
  2047. status = ERROR_INVALID_PARAMETER;
  2048. goto error_exit;
  2049. }
  2050. if (networkCount == 0) {
  2051. status = ERROR_INVALID_PARAMETER;
  2052. goto error_exit;
  2053. }
  2054. networkList = LocalAlloc(
  2055. LMEM_ZEROINIT| LMEM_FIXED,
  2056. networkCount * sizeof(PNM_NETWORK)
  2057. );
  2058. if (networkList == NULL) {
  2059. status = ERROR_NOT_ENOUGH_MEMORY;
  2060. goto error_exit;
  2061. }
  2062. //
  2063. // Start a transaction - this must be done before acquiring the NM lock.
  2064. //
  2065. xaction = DmBeginLocalUpdate();
  2066. if (xaction == NULL) {
  2067. status = GetLastError();
  2068. ClRtlLogPrint(LOG_CRITICAL,
  2069. "[NM] Failed to start a transaction, status %1!u!\n",
  2070. status
  2071. );
  2072. goto error_exit;
  2073. }
  2074. NmpAcquireLock(); isLockAcquired = TRUE;
  2075. if (NmpJoinerNodeId != ClusterInvalidNodeId) {
  2076. status = ERROR_CLUSTER_JOIN_IN_PROGRESS;
  2077. ClRtlLogPrint(LOG_NOISE,
  2078. "[NM] Cannot set network priority order because a node is "
  2079. "joining the cluster.\n"
  2080. );
  2081. goto error_exit;
  2082. }
  2083. for (i=0; i<networkCount; i++) {
  2084. networkId = ClRtlMultiSzEnum(
  2085. NetworkIdList,
  2086. multiSzLength,
  2087. i
  2088. );
  2089. CL_ASSERT(networkId != NULL);
  2090. networkList[i] = OmReferenceObjectById(
  2091. ObjectTypeNetwork,
  2092. networkId
  2093. );
  2094. if (networkList[i] == NULL) {
  2095. goto error_exit;
  2096. }
  2097. }
  2098. //
  2099. // Verify that all of the networks specified are internal, and
  2100. // that all of the internal networks are specified.
  2101. //
  2102. if (networkCount != NmpInternalNetworkCount) {
  2103. ClRtlLogPrint(LOG_CRITICAL,
  2104. "[NM] Supplied network count %1!u! doesn't match internal "
  2105. "network count %2!u!\n",
  2106. networkCount,
  2107. NmpInternalNetworkCount
  2108. );
  2109. status = ERROR_INVALID_PARAMETER;
  2110. goto error_exit;
  2111. }
  2112. for (entry = NmpInternalNetworkList.Flink, matchCount = 0;
  2113. entry != &NmpInternalNetworkList;
  2114. entry = entry->Flink
  2115. )
  2116. {
  2117. network = CONTAINING_RECORD(entry, NM_NETWORK, InternalLinkage);
  2118. if (NmpIsNetworkForInternalUse(network)) {
  2119. for (i=0; i<networkCount; i++) {
  2120. if (network == networkList[i]) {
  2121. matchCount++;
  2122. break;
  2123. }
  2124. }
  2125. if (i == networkCount) {
  2126. //
  2127. // This network is not in the list.
  2128. //
  2129. ClRtlLogPrint(LOG_CRITICAL,
  2130. "[NM] Internal use network %1!ws! is not in priority "
  2131. "list\n",
  2132. (LPWSTR) OmObjectId(network)
  2133. );
  2134. status = ERROR_INVALID_PARAMETER;
  2135. goto error_exit;
  2136. }
  2137. }
  2138. }
  2139. if (matchCount != networkCount) {
  2140. //
  2141. // Some of the specified networks are not internal use.
  2142. //
  2143. ClRtlLogPrint(LOG_CRITICAL,
  2144. "[NM] Some non-internal use networks are in priority list\n"
  2145. );
  2146. status = ERROR_INVALID_PARAMETER;
  2147. goto error_exit;
  2148. }
  2149. //
  2150. // The list is kosher. Set the priorities.
  2151. //
  2152. status = NmpSetNetworkPriorityOrder(networkCount, networkList, xaction);
  2153. error_exit:
  2154. if (isLockAcquired) {
  2155. NmpLockedLeaveApi();
  2156. NmpReleaseLock();
  2157. }
  2158. else {
  2159. NmpLeaveApi();
  2160. }
  2161. if (xaction != NULL) {
  2162. //
  2163. // Complete the transaction - this must be done after releasing
  2164. // the NM lock.
  2165. //
  2166. if (status == ERROR_SUCCESS) {
  2167. DmCommitLocalUpdate(xaction);
  2168. }
  2169. else {
  2170. DmAbortLocalUpdate(xaction);
  2171. }
  2172. }
  2173. if (networkList != NULL) {
  2174. for (i=0; i<networkCount; i++) {
  2175. if (networkList[i] != NULL) {
  2176. OmDereferenceObject(networkList[i]);
  2177. }
  2178. }
  2179. LocalFree(networkList);
  2180. }
  2181. return(status);
  2182. } // NmpUpdateSetNetworkPriorityOrder
  2183. DWORD
  2184. NmpSetNetworkPriorityOrder(
  2185. IN DWORD NetworkCount,
  2186. IN PNM_NETWORK * NetworkList,
  2187. IN HLOCALXSACTION Xaction
  2188. )
  2189. /*++
  2190. Notes:
  2191. Called with NM Lock held.
  2192. --*/
  2193. {
  2194. DWORD status = ERROR_SUCCESS;
  2195. PNM_NETWORK network;
  2196. DWORD i;
  2197. LPCWSTR networkId;
  2198. HDMKEY networkKey;
  2199. DWORD priority;
  2200. //
  2201. // Update the database first.
  2202. //
  2203. for (i=0, priority = 1; i<NetworkCount; i++, priority++) {
  2204. network = NetworkList[i];
  2205. networkId = OmObjectId(network);
  2206. CL_ASSERT(NmpIsNetworkForInternalUse(network));
  2207. if (network->Priority != priority) {
  2208. networkKey = DmOpenKey(DmNetworksKey, networkId, KEY_WRITE);
  2209. if (networkKey == NULL) {
  2210. status = GetLastError();
  2211. ClRtlLogPrint(LOG_CRITICAL,
  2212. "[NM] Failed to open database key for network %1!ws!, "
  2213. "status %2!u!\n",
  2214. networkId,
  2215. status
  2216. );
  2217. return(status);
  2218. }
  2219. status = DmLocalSetValue(
  2220. Xaction,
  2221. networkKey,
  2222. CLUSREG_NAME_NET_PRIORITY,
  2223. REG_DWORD,
  2224. (CONST BYTE *) &priority,
  2225. sizeof(priority)
  2226. );
  2227. DmCloseKey(networkKey);
  2228. if (status != ERROR_SUCCESS) {
  2229. ClRtlLogPrint(LOG_CRITICAL,
  2230. "[NM] Set of priority value failed for network %1!ws!, "
  2231. "status %2!u!.\n",
  2232. networkId,
  2233. status
  2234. );
  2235. return(status);
  2236. }
  2237. }
  2238. }
  2239. #ifdef CLUSTER_TESTPOINT
  2240. TESTPT(TpFailNmSetNetworkPriorityOrder) {
  2241. status = 999999;
  2242. return(status);
  2243. }
  2244. #endif
  2245. //
  2246. // Update the in-memory representation
  2247. //
  2248. InitializeListHead(&NmpInternalNetworkList);
  2249. for (i=0, priority = 1; i<NetworkCount; i++, priority++) {
  2250. network = NetworkList[i];
  2251. networkId = OmObjectId(network);
  2252. InsertTailList(
  2253. &NmpInternalNetworkList,
  2254. &(network->InternalLinkage)
  2255. );
  2256. if (network->Priority != priority) {
  2257. ClRtlLogPrint(LOG_NOISE,
  2258. "[NM] Set priority for network %1!ws! to %2!u!.\n",
  2259. networkId,
  2260. priority
  2261. );
  2262. network->Priority = priority;
  2263. //
  2264. // If the local node is attached to this network, set its
  2265. // priority in the cluster transport
  2266. //
  2267. if (NmpIsNetworkRegistered(network)) {
  2268. status = ClusnetSetNetworkPriority(
  2269. NmClusnetHandle,
  2270. network->ShortId,
  2271. network->Priority
  2272. );
  2273. #ifdef CLUSTER_TESTPOINT
  2274. TESTPT(TpFailNmSetNetworkPriorityOrder2) {
  2275. status = 999999;
  2276. }
  2277. #endif
  2278. if (status != ERROR_SUCCESS) {
  2279. //
  2280. // We can't easily abort here. We must either continue
  2281. // or commit suicide. We choose to continue and log an
  2282. // event.
  2283. //
  2284. WCHAR string[16];
  2285. wsprintfW(&(string[0]), L"%u", status);
  2286. CsLogEvent2(
  2287. LOG_UNUSUAL,
  2288. NM_EVENT_SET_NETWORK_PRIORITY_FAILED,
  2289. OmObjectName(network),
  2290. string
  2291. );
  2292. ClRtlLogPrint(LOG_CRITICAL,
  2293. "[NM] Cluster transport failed to set priority for "
  2294. "network %1!ws!, status %2!u!\n",
  2295. networkId,
  2296. status
  2297. );
  2298. status = ERROR_SUCCESS;
  2299. }
  2300. }
  2301. }
  2302. }
  2303. CL_ASSERT(status == ERROR_SUCCESS);
  2304. //
  2305. // Issue a cluster property change event.
  2306. //
  2307. NmpIssueClusterPropertyChangeEvent();
  2308. return(ERROR_SUCCESS);
  2309. } // NmpSetNetworkPriorityOrder
  2310. DWORD
  2311. NmpUpdateSetNetworkCommonProperties(
  2312. IN BOOL IsSourceNode,
  2313. IN LPWSTR NetworkId,
  2314. IN UCHAR * PropertyList,
  2315. IN LPDWORD PropertyListLength
  2316. )
  2317. /*++
  2318. Routine Description:
  2319. Global update handler for setting the common properties of a network.
  2320. Arguments:
  2321. IsSourceNode - Set to TRUE if this node is the source of the update.
  2322. Set to FALSE otherwise.
  2323. NetworkId - A pointer to a unicode string containing the ID of the
  2324. network to update.
  2325. Return Value:
  2326. ERROR_SUCCESS if the routine succeeds.
  2327. A Win32 error code otherwise.
  2328. --*/
  2329. {
  2330. DWORD status = ERROR_SUCCESS;
  2331. NM_NETWORK_INFO networkInfo;
  2332. PNM_NETWORK network = NULL;
  2333. HLOCALXSACTION xaction = NULL;
  2334. HDMKEY networkKey = NULL;
  2335. DWORD descSize = 0;
  2336. LPWSTR descBuffer = NULL;
  2337. BOOLEAN propertyChanged = FALSE;
  2338. BOOLEAN isLockAcquired = FALSE;
  2339. if (!NmpEnterApi(NmStateOnline)) {
  2340. ClRtlLogPrint(LOG_NOISE,
  2341. "[NM] Not in valid state to process SetNetworkCommonProperties "
  2342. "update.\n"
  2343. );
  2344. return(ERROR_NODE_NOT_AVAILABLE);
  2345. }
  2346. ClRtlLogPrint(LOG_NOISE,
  2347. "[NM] Received update to set common properties for network %1!ws!.\n",
  2348. NetworkId
  2349. );
  2350. ZeroMemory(&networkInfo, sizeof(NM_NETWORK_INFO));
  2351. //
  2352. // Find the network's object
  2353. //
  2354. network = OmReferenceObjectById(ObjectTypeNetwork, NetworkId);
  2355. if (network == NULL) {
  2356. ClRtlLogPrint(LOG_CRITICAL,
  2357. "[NM] Unable to find network %1!ws!.\n",
  2358. NetworkId
  2359. );
  2360. status = ERROR_CLUSTER_NETWORK_NOT_FOUND;
  2361. goto error_exit;
  2362. }
  2363. //
  2364. // Open the network's database key
  2365. //
  2366. networkKey = DmOpenKey(DmNetworksKey, NetworkId, KEY_WRITE);
  2367. if (networkKey == NULL) {
  2368. status = GetLastError();
  2369. ClRtlLogPrint(LOG_CRITICAL,
  2370. "[NM] Failed to open database key for network %1!ws!, "
  2371. "status %2!u!\n",
  2372. NetworkId,
  2373. status
  2374. );
  2375. goto error_exit;
  2376. }
  2377. //
  2378. // Start a transaction - this must be done before acquiring the NM lock.
  2379. //
  2380. xaction = DmBeginLocalUpdate();
  2381. if (xaction == NULL) {
  2382. status = GetLastError();
  2383. ClRtlLogPrint(LOG_CRITICAL,
  2384. "[NM] Failed to begin a transaction, status %1!u!\n",
  2385. status
  2386. );
  2387. goto error_exit;
  2388. }
  2389. NmpAcquireLock(); isLockAcquired = TRUE;
  2390. if (NmpJoinerNodeId != ClusterInvalidNodeId) {
  2391. status = ERROR_CLUSTER_JOIN_IN_PROGRESS;
  2392. ClRtlLogPrint(LOG_NOISE,
  2393. "[NM] Cannot set network common properties because a node is "
  2394. "joining the cluster.\n"
  2395. );
  2396. goto error_exit;
  2397. }
  2398. //
  2399. // Validate the property list and convert it to a network params struct.
  2400. //
  2401. status = NmpNetworkValidateCommonProperties(
  2402. network,
  2403. PropertyList,
  2404. *PropertyListLength,
  2405. &networkInfo
  2406. );
  2407. if (status != ERROR_SUCCESS) {
  2408. ClRtlLogPrint(LOG_CRITICAL,
  2409. "[NM] Property list validation failed, status %1!u!.\n",
  2410. status
  2411. );
  2412. goto error_exit;
  2413. }
  2414. CL_ASSERT(network->Priority == networkInfo.Priority);
  2415. CL_ASSERT(wcscmp(NetworkId, networkInfo.Id) == 0);
  2416. CL_ASSERT(wcscmp(OmObjectName(network), networkInfo.Name) == 0);
  2417. CL_ASSERT(wcscmp(network->Transport, networkInfo.Transport) == 0);
  2418. CL_ASSERT(wcscmp(network->Address, networkInfo.Address) == 0);
  2419. CL_ASSERT(wcscmp(network->AddressMask, networkInfo.AddressMask) == 0);
  2420. //
  2421. // Check if the network's description has changed.
  2422. //
  2423. if (wcscmp(network->Description, networkInfo.Description) != 0) {
  2424. ClRtlLogPrint(LOG_NOISE,
  2425. "[NM] Setting description for network %1!ws! to %2!ws!.\n",
  2426. NetworkId,
  2427. networkInfo.Description
  2428. );
  2429. //
  2430. // Allocate a buffer for the description string
  2431. //
  2432. descSize = NM_WCSLEN(networkInfo.Description);
  2433. descBuffer = MIDL_user_allocate(descSize);
  2434. if (descBuffer == NULL) {
  2435. status = ERROR_NOT_ENOUGH_MEMORY;
  2436. goto error_exit;
  2437. }
  2438. RtlMoveMemory(descBuffer, networkInfo.Description, descSize);
  2439. //
  2440. // Update the database
  2441. //
  2442. status = DmLocalSetValue(
  2443. xaction,
  2444. networkKey,
  2445. CLUSREG_NAME_NET_DESC,
  2446. REG_SZ,
  2447. (CONST BYTE *) networkInfo.Description,
  2448. descSize
  2449. );
  2450. if (status != ERROR_SUCCESS) {
  2451. ClRtlLogPrint(LOG_CRITICAL,
  2452. "[NM] Set of description value failed for network %1!ws!, "
  2453. "status %2!u!.\n",
  2454. NetworkId,
  2455. status
  2456. );
  2457. goto error_exit;
  2458. }
  2459. //
  2460. // Updating the network object is deferred until the transaction
  2461. // commits.
  2462. //
  2463. propertyChanged = TRUE;
  2464. }
  2465. #ifdef CLUSTER_TESTPOINT
  2466. TESTPT(TpFailNmSetNetworkCommonProperties) {
  2467. status = 999999;
  2468. goto error_exit;
  2469. }
  2470. #endif
  2471. //
  2472. // Check if the network's role has changed.
  2473. //
  2474. //
  2475. // NOTE: This operation is not guaranteed to be reversible, so it must
  2476. // be the last thing we do in this routine. If it succeeds, the
  2477. // update must be committed.
  2478. //
  2479. if ( network->Role != ((CLUSTER_NETWORK_ROLE) networkInfo.Role) ) {
  2480. status = NmpSetNetworkRole(
  2481. network,
  2482. networkInfo.Role,
  2483. xaction,
  2484. networkKey
  2485. );
  2486. if (status != ERROR_SUCCESS) {
  2487. goto error_exit;
  2488. }
  2489. propertyChanged = TRUE;
  2490. }
  2491. if (propertyChanged) {
  2492. //
  2493. // Commit the updates to the network object in memory
  2494. //
  2495. if (descBuffer != NULL) {
  2496. MIDL_user_free(network->Description);
  2497. network->Description = descBuffer;
  2498. descBuffer = NULL;
  2499. }
  2500. //
  2501. // Issue a network property change event.
  2502. //
  2503. if (propertyChanged && (status == ERROR_SUCCESS)) {
  2504. ClusterEvent(CLUSTER_EVENT_NETWORK_PROPERTY_CHANGE, network);
  2505. }
  2506. }
  2507. CL_ASSERT(status == ERROR_SUCCESS);
  2508. error_exit:
  2509. if (isLockAcquired) {
  2510. NmpLockedLeaveApi();
  2511. NmpReleaseLock();
  2512. }
  2513. else {
  2514. NmpLeaveApi();
  2515. }
  2516. if (xaction != NULL) {
  2517. //
  2518. // Complete the transaction - this must be done after releasing
  2519. // the NM lock.
  2520. //
  2521. if (propertyChanged && (status == ERROR_SUCCESS)) {
  2522. DmCommitLocalUpdate(xaction);
  2523. }
  2524. else {
  2525. DmAbortLocalUpdate(xaction);
  2526. }
  2527. }
  2528. ClNetFreeNetworkInfo(&networkInfo);
  2529. if (descBuffer != NULL) {
  2530. MIDL_user_free(descBuffer);
  2531. }
  2532. if (networkKey != NULL) {
  2533. DmCloseKey(networkKey);
  2534. }
  2535. if (network != NULL) {
  2536. OmDereferenceObject(network);
  2537. }
  2538. return(status);
  2539. } // NmpUpdateSetNetworkCommonProperties
  2540. DWORD
  2541. NmpUpdateSetNetworkAndInterfaceStates(
  2542. IN BOOL IsSourceNode,
  2543. IN LPWSTR NetworkId,
  2544. IN CLUSTER_NETWORK_STATE * NewNetworkState,
  2545. IN PNM_STATE_ENTRY InterfaceStateVector,
  2546. IN LPDWORD InterfaceStateVectorSize
  2547. )
  2548. {
  2549. DWORD status = ERROR_SUCCESS;
  2550. PNM_NETWORK network;
  2551. NmpAcquireLock();
  2552. if (NmpLockedEnterApi(NmStateOnline)) {
  2553. ClRtlLogPrint(LOG_NOISE,
  2554. "[NM] Received update to set state for network %1!ws!.\n",
  2555. NetworkId
  2556. );
  2557. //
  2558. // Find the network's object
  2559. //
  2560. network = OmReferenceObjectById(ObjectTypeNetwork, NetworkId);
  2561. if (network != NULL) {
  2562. NmpSetNetworkAndInterfaceStates(
  2563. network,
  2564. *NewNetworkState,
  2565. InterfaceStateVector,
  2566. *InterfaceStateVectorSize
  2567. );
  2568. OmDereferenceObject(network);
  2569. }
  2570. else {
  2571. ClRtlLogPrint(LOG_CRITICAL,
  2572. "[NM] Unable to find network %1!ws!.\n",
  2573. NetworkId
  2574. );
  2575. status = ERROR_CLUSTER_NETWORK_NOT_FOUND;
  2576. }
  2577. }
  2578. else {
  2579. ClRtlLogPrint(LOG_NOISE,
  2580. "[NM] Not in valid state to process SetNetworkAndInterfaceStates "
  2581. "update.\n"
  2582. );
  2583. status = ERROR_NODE_NOT_AVAILABLE;
  2584. }
  2585. NmpLockedLeaveApi();
  2586. NmpReleaseLock();
  2587. return(status);
  2588. } // NmpUpdateSetNetworkAndInterfaceStates
  2589. /////////////////////////////////////////////////////////////////////////////
  2590. //
  2591. // Helper routines for updates
  2592. //
  2593. /////////////////////////////////////////////////////////////////////////////
  2594. DWORD
  2595. NmpSetNetworkRole(
  2596. PNM_NETWORK Network,
  2597. CLUSTER_NETWORK_ROLE NewRole,
  2598. HLOCALXSACTION Xaction,
  2599. HDMKEY NetworkKey
  2600. )
  2601. /*++
  2602. Called with the NmpLock acquired.
  2603. This operation is not guaranteed to be reversible, so this
  2604. function is coded such that it either succeeds and makes the update
  2605. or it fails and no update is made.
  2606. --*/
  2607. {
  2608. DWORD status = ERROR_SUCCESS;
  2609. CLUSTER_NETWORK_ROLE oldRole = Network->Role;
  2610. DWORD dwordNewRole = (DWORD) NewRole;
  2611. LPCWSTR networkId = OmObjectId(Network);
  2612. DWORD oldPriority = Network->Priority;
  2613. DWORD newPriority = oldPriority;
  2614. BOOLEAN internalNetworkListChanged = FALSE;
  2615. ClRtlLogPrint(LOG_NOISE,
  2616. "[NM] Changing role for network %1!ws! to %2!u!\n",
  2617. networkId,
  2618. NewRole
  2619. );
  2620. CL_ASSERT(NewRole != oldRole);
  2621. CL_ASSERT(
  2622. NmpValidateNetworkRoleChange(Network, NewRole) == ERROR_SUCCESS
  2623. );
  2624. //
  2625. // First, make any registry updates since these can be
  2626. // aborted by the caller.
  2627. //
  2628. //
  2629. // Update the role property.
  2630. //
  2631. status = DmLocalSetValue(
  2632. Xaction,
  2633. NetworkKey,
  2634. CLUSREG_NAME_NET_ROLE,
  2635. REG_DWORD,
  2636. (CONST BYTE *) &dwordNewRole,
  2637. sizeof(DWORD)
  2638. );
  2639. if (status != ERROR_SUCCESS) {
  2640. ClRtlLogPrint(LOG_CRITICAL,
  2641. "[NM] Set of role value failed for network %1!ws!, "
  2642. "status %2!u!.\n",
  2643. networkId,
  2644. status
  2645. );
  2646. return(status);
  2647. }
  2648. //
  2649. // Update the priority property, if needed.
  2650. //
  2651. if (oldRole & ClusterNetworkRoleInternalUse) {
  2652. if (!(NewRole & ClusterNetworkRoleInternalUse)) {
  2653. //
  2654. // This network is no longer used for internal communication.
  2655. // Invalidate its priority value.
  2656. //
  2657. newPriority = 0xFFFFFFFF;
  2658. internalNetworkListChanged = TRUE;
  2659. }
  2660. }
  2661. else if (NewRole & ClusterNetworkRoleInternalUse) {
  2662. //
  2663. // This network is now used for internal communication.
  2664. // The network's priority is one greater than that of the lowest
  2665. // (numerically highest) priority network already in the list.
  2666. //
  2667. if (IsListEmpty(&NmpInternalNetworkList)) {
  2668. newPriority = 1;
  2669. }
  2670. else {
  2671. PNM_NETWORK network = CONTAINING_RECORD(
  2672. NmpInternalNetworkList.Blink,
  2673. NM_NETWORK,
  2674. InternalLinkage
  2675. );
  2676. CL_ASSERT(network->Priority != 0);
  2677. CL_ASSERT(network->Priority != 0xFFFFFFFF);
  2678. newPriority = network->Priority + 1;
  2679. }
  2680. internalNetworkListChanged = TRUE;
  2681. }
  2682. if (newPriority != oldPriority) {
  2683. status = DmLocalSetValue(
  2684. Xaction,
  2685. NetworkKey,
  2686. CLUSREG_NAME_NET_PRIORITY,
  2687. REG_DWORD,
  2688. (CONST BYTE *) &newPriority,
  2689. sizeof(newPriority)
  2690. );
  2691. if (status != ERROR_SUCCESS) {
  2692. ClRtlLogPrint(LOG_CRITICAL,
  2693. "[NM] Failed to set priority value for network %1!ws!, "
  2694. "status %2!u!.\n",
  2695. networkId,
  2696. status
  2697. );
  2698. return(status);
  2699. }
  2700. }
  2701. //
  2702. // Update the network object. Some of the subsequent subroutine calls
  2703. // depend on this.
  2704. //
  2705. Network->Role = NewRole;
  2706. Network->Priority = newPriority;
  2707. //
  2708. // Do other housekeeping based on the change.
  2709. //
  2710. // Note that the housekeeping work is coded such that none of it needs
  2711. // to be reversed if an error occurs.
  2712. //
  2713. if (NewRole == ClusterNetworkRoleNone) {
  2714. PLIST_ENTRY entry;
  2715. PNM_INTERFACE netInterface;
  2716. //
  2717. // Case 1: This network is no longer used for clustering.
  2718. //
  2719. if (NmpIsNetworkRegistered(Network)) {
  2720. //
  2721. // Delete the network from the cluster transport.
  2722. // This will delete all of its interfaces as well.
  2723. //
  2724. NmpDeregisterNetwork(Network);
  2725. ClRtlLogPrint(LOG_NOISE,
  2726. "[NM] No longer hearbeating on network %1!ws!.\n",
  2727. networkId
  2728. );
  2729. }
  2730. //
  2731. // Invalidate the connectivity data for all interfaces on
  2732. // the network.
  2733. //
  2734. for ( entry = Network->InterfaceList.Flink;
  2735. entry != &(Network->InterfaceList);
  2736. entry = entry->Flink
  2737. )
  2738. {
  2739. netInterface = CONTAINING_RECORD(
  2740. entry,
  2741. NM_INTERFACE,
  2742. NetworkLinkage
  2743. );
  2744. NmpSetInterfaceConnectivityData(
  2745. Network,
  2746. netInterface->NetIndex,
  2747. ClusterNetInterfaceUnavailable
  2748. );
  2749. }
  2750. //
  2751. // Clean up tracking data.
  2752. //
  2753. if (oldRole & ClusterNetworkRoleInternalUse) {
  2754. RemoveEntryList(&(Network->InternalLinkage));
  2755. CL_ASSERT(NmpInternalNetworkCount > 0);
  2756. NmpInternalNetworkCount--;
  2757. }
  2758. if (oldRole & ClusterNetworkRoleClientAccess) {
  2759. CL_ASSERT(NmpClientNetworkCount > 0);
  2760. NmpClientNetworkCount--;
  2761. }
  2762. //
  2763. // Use the NT5 state logic.
  2764. //
  2765. if (NmpLeaderNodeId == NmLocalNodeId) {
  2766. //
  2767. // Schedule an immediate state update.
  2768. //
  2769. NmpScheduleNetworkStateRecalc(Network);
  2770. }
  2771. //
  2772. // Stop multicast configuration.
  2773. //
  2774. NmpStopMulticast(Network);
  2775. }
  2776. else if (oldRole == ClusterNetworkRoleNone) {
  2777. //
  2778. // Case 2: This network is now used for clustering.
  2779. //
  2780. if (Network->LocalInterface != NULL) {
  2781. //
  2782. // Register this network with the cluster transport.
  2783. //
  2784. // Note that this action will trigger a connectivity report,
  2785. // which will in turn trigger a state update under the NT5 logic.
  2786. //
  2787. status = NmpRegisterNetwork(
  2788. Network,
  2789. TRUE // Do retry on failure
  2790. );
  2791. if (status != ERROR_SUCCESS) {
  2792. goto error_exit;
  2793. }
  2794. ClRtlLogPrint(LOG_NOISE,
  2795. "[NM] Now heartbeating on network %1!ws!.\n",
  2796. networkId
  2797. );
  2798. }
  2799. else if (NmpLeaderNodeId == NmLocalNodeId) {
  2800. //
  2801. // Schedule a delayed state update in case none of the other
  2802. // nodes attached to this network are up right now.
  2803. //
  2804. NmpStartNetworkStateRecalcTimer(
  2805. Network,
  2806. NM_NET_STATE_RECALC_TIMEOUT
  2807. );
  2808. }
  2809. //
  2810. // Update tracking data.
  2811. //
  2812. if (NewRole & ClusterNetworkRoleInternalUse) {
  2813. InsertTailList(
  2814. &NmpInternalNetworkList,
  2815. &(Network->InternalLinkage)
  2816. );
  2817. NmpInternalNetworkCount++;
  2818. }
  2819. if (NewRole & ClusterNetworkRoleClientAccess) {
  2820. NmpClientNetworkCount++;
  2821. }
  2822. //
  2823. // Start multicast.
  2824. //
  2825. NmpStartMulticast(Network, NmStartMulticastDynamic);
  2826. }
  2827. else {
  2828. //
  2829. // Case 3: We are using the network in a different way now.
  2830. // Note that the network is already registered with
  2831. // the cluster transport and will remain so. As a result,
  2832. // there is no need to perform a state update.
  2833. //
  2834. //
  2835. // First, examine the former and new use of the
  2836. // network for internal communication, and make any
  2837. // necessary updates to the cluster transport.
  2838. //
  2839. if (oldRole & ClusterNetworkRoleInternalUse) {
  2840. if (!(NewRole & ClusterNetworkRoleInternalUse)) {
  2841. //
  2842. // This network is no longer used for internal communication.
  2843. // It is used for client access.
  2844. //
  2845. CL_ASSERT(NewRole & ClusterNetworkRoleClientAccess);
  2846. if (NmpIsNetworkRegistered(Network)) {
  2847. //
  2848. // Restrict the network to heartbeats only.
  2849. //
  2850. status = ClusnetSetNetworkRestriction(
  2851. NmClusnetHandle,
  2852. Network->ShortId,
  2853. TRUE, // Network is restricted
  2854. 0
  2855. );
  2856. if (status != ERROR_SUCCESS) {
  2857. ClRtlLogPrint(LOG_CRITICAL,
  2858. "[NM] Failed to restrict network %1!ws!, "
  2859. "status %2!u!.\n",
  2860. networkId,
  2861. status
  2862. );
  2863. goto error_exit;
  2864. }
  2865. }
  2866. //
  2867. // Update tracking data
  2868. //
  2869. RemoveEntryList(&(Network->InternalLinkage));
  2870. CL_ASSERT(NmpInternalNetworkCount > 0);
  2871. NmpInternalNetworkCount--;
  2872. }
  2873. }
  2874. else {
  2875. //
  2876. // The network is now used for internal communication.
  2877. //
  2878. CL_ASSERT(NewRole & ClusterNetworkRoleInternalUse);
  2879. if (NmpIsNetworkRegistered(Network)) {
  2880. //
  2881. // Clear the restriction and set the priority.
  2882. //
  2883. status = ClusnetSetNetworkRestriction(
  2884. NmClusnetHandle,
  2885. Network->ShortId,
  2886. FALSE, // Network is not restricted
  2887. newPriority
  2888. );
  2889. if (status != ERROR_SUCCESS) {
  2890. ClRtlLogPrint(LOG_CRITICAL,
  2891. "[NM] Failed to unrestrict network %1!ws!, "
  2892. "status %2!u!.\n",
  2893. networkId,
  2894. status
  2895. );
  2896. goto error_exit;
  2897. }
  2898. }
  2899. //
  2900. // Update the tracking data
  2901. //
  2902. InsertTailList(
  2903. &NmpInternalNetworkList,
  2904. &(Network->InternalLinkage)
  2905. );
  2906. NmpInternalNetworkCount++;
  2907. }
  2908. //
  2909. // Now update the remaining tracking data based on former and
  2910. // current use of the network for client access.
  2911. //
  2912. if (oldRole & ClusterNetworkRoleClientAccess) {
  2913. if (!(NewRole & ClusterNetworkRoleClientAccess)) {
  2914. //
  2915. // This network is no longer used for client access.
  2916. //
  2917. CL_ASSERT(NmpClientNetworkCount > 0);
  2918. NmpClientNetworkCount--;
  2919. }
  2920. }
  2921. else {
  2922. //
  2923. // This network is now used for client access.
  2924. //
  2925. CL_ASSERT(NewRole & ClusterNetworkRoleClientAccess);
  2926. NmpClientNetworkCount++;
  2927. }
  2928. }
  2929. if (internalNetworkListChanged) {
  2930. NmpIssueClusterPropertyChangeEvent();
  2931. }
  2932. return(ERROR_SUCCESS);
  2933. error_exit:
  2934. //
  2935. // Undo the updates to the network object.
  2936. //
  2937. Network->Role = oldRole;
  2938. Network->Priority = oldPriority;
  2939. return(status);
  2940. } // NmpSetNetworkRole
  2941. VOID
  2942. NmpSetNetworkAndInterfaceStates(
  2943. IN PNM_NETWORK Network,
  2944. IN CLUSTER_NETWORK_STATE NewNetworkState,
  2945. IN PNM_STATE_ENTRY InterfaceStateVector,
  2946. IN DWORD VectorSize
  2947. )
  2948. /*++
  2949. Notes:
  2950. Called with NmpLock held.
  2951. Because NM_STATE_ENTRY is an unsigned type, while
  2952. CLUSTER_NETINTERFACE_STATE is a signed type, and
  2953. ClusterNetInterfaceStateUnknown is defined to be -1, we cannot cast
  2954. from NM_STATE_ENTRY to CLUSTER_NETINTERFACE_STATE and preserve the
  2955. value of ClusterNetInterfaceStateUnknown.
  2956. --*/
  2957. {
  2958. PLIST_ENTRY entry;
  2959. PNM_INTERFACE netInterface;
  2960. PNM_NODE node;
  2961. DWORD logLevel, logCode;
  2962. DWORD ifNetIndex;
  2963. LPCWSTR netInterfaceId;
  2964. LPCWSTR nodeName;
  2965. LPCWSTR networkName = OmObjectName(Network);
  2966. LPCWSTR networkId = OmObjectId(Network);
  2967. //
  2968. // Examine each interface on this network to see if its state
  2969. // has changed.
  2970. //
  2971. for ( entry = Network->InterfaceList.Flink;
  2972. entry != &(Network->InterfaceList);
  2973. entry = entry->Flink
  2974. )
  2975. {
  2976. netInterface = CONTAINING_RECORD(
  2977. entry,
  2978. NM_INTERFACE,
  2979. NetworkLinkage
  2980. );
  2981. ifNetIndex = netInterface->NetIndex;
  2982. netInterfaceId = OmObjectId(netInterface);
  2983. node = netInterface->Node;
  2984. nodeName = OmObjectName(node);
  2985. if ( (ifNetIndex < VectorSize) &&
  2986. (InterfaceStateVector[ifNetIndex] !=
  2987. (NM_STATE_ENTRY) netInterface->State
  2988. )
  2989. )
  2990. {
  2991. BOOLEAN logEvent = FALSE;
  2992. CLUSTER_EVENT eventCode = 0;
  2993. NM_STATE_ENTRY newState = InterfaceStateVector[ifNetIndex];
  2994. if (newState == (NM_STATE_ENTRY) ClusterNetInterfaceUnavailable) {
  2995. //
  2996. // Either the node has gone down or the network has been
  2997. // disabled.
  2998. //
  2999. netInterface->State = ClusterNetInterfaceUnavailable;
  3000. eventCode = CLUSTER_EVENT_NETINTERFACE_UNAVAILABLE;
  3001. ClRtlLogPrint(LOG_UNUSUAL,
  3002. "[NM] Interface %1!ws! is unavailable (node: %2!ws!, "
  3003. "network: %3!ws!).\n",
  3004. netInterfaceId,
  3005. nodeName,
  3006. networkName
  3007. );
  3008. }
  3009. else if (newState == (NM_STATE_ENTRY) ClusterNetInterfaceUp) {
  3010. netInterface->State = ClusterNetInterfaceUp;
  3011. eventCode = CLUSTER_EVENT_NETINTERFACE_UP;
  3012. logCode = NM_EVENT_CLUSTER_NETINTERFACE_UP;
  3013. logLevel = LOG_NOISE;
  3014. logEvent = TRUE;
  3015. ClRtlLogPrint(LOG_NOISE,
  3016. "[NM] Interface %1!ws! is up (node: %2!ws!, "
  3017. "network: %3!ws!).\n",
  3018. netInterfaceId,
  3019. nodeName,
  3020. networkName
  3021. );
  3022. }
  3023. else if ( newState ==
  3024. (NM_STATE_ENTRY) ClusterNetInterfaceUnreachable
  3025. )
  3026. {
  3027. netInterface->State = ClusterNetInterfaceUnreachable;
  3028. eventCode = CLUSTER_EVENT_NETINTERFACE_UNREACHABLE;
  3029. logCode = NM_EVENT_CLUSTER_NETINTERFACE_UNREACHABLE;
  3030. logLevel = LOG_UNUSUAL;
  3031. logEvent = TRUE;
  3032. ClRtlLogPrint(LOG_UNUSUAL,
  3033. "[NM] Interface %1!ws! is unreachable (node: %2!ws!, "
  3034. "network: %3!ws!).\n",
  3035. netInterfaceId,
  3036. nodeName,
  3037. networkName
  3038. );
  3039. }
  3040. else if (newState == (NM_STATE_ENTRY) ClusterNetInterfaceFailed) {
  3041. netInterface->State = ClusterNetInterfaceFailed;
  3042. eventCode = CLUSTER_EVENT_NETINTERFACE_FAILED;
  3043. logCode = NM_EVENT_CLUSTER_NETINTERFACE_FAILED;
  3044. logLevel = LOG_UNUSUAL;
  3045. logEvent = TRUE;
  3046. ClRtlLogPrint(LOG_UNUSUAL,
  3047. "[NM] Interface %1!ws! failed (node: %2!ws!, "
  3048. "network: %3!ws!).\n",
  3049. netInterfaceId,
  3050. nodeName,
  3051. networkName
  3052. );
  3053. }
  3054. else if ( newState ==
  3055. (NM_STATE_ENTRY) ClusterNetInterfaceStateUnknown
  3056. )
  3057. {
  3058. //
  3059. // This case can happen if a create update races with a
  3060. // state update. This will be the new interface. Just
  3061. // ignore it. Another state update will arrive shortly.
  3062. //
  3063. ClRtlLogPrint(LOG_UNUSUAL,
  3064. "[NM] State for interface %1!ws! is unknown "
  3065. "(node: %2!ws!, network: %3!ws!).\n",
  3066. netInterfaceId,
  3067. nodeName,
  3068. networkName
  3069. );
  3070. }
  3071. else {
  3072. ClRtlLogPrint(LOG_UNUSUAL,
  3073. "[NM] UpdateInterfaceState: Invalid state %1!u! "
  3074. "specified for interface %2!ws!\n",
  3075. newState,
  3076. netInterfaceId
  3077. );
  3078. CL_ASSERT(FALSE);
  3079. }
  3080. if (eventCode != 0) {
  3081. ClusterEvent(eventCode, netInterface);
  3082. }
  3083. if (logEvent && (NmpLeaderNodeId == NmLocalNodeId)) {
  3084. CsLogEvent2(
  3085. logLevel,
  3086. logCode,
  3087. nodeName,
  3088. networkName
  3089. );
  3090. }
  3091. }
  3092. }
  3093. if (Network->State != NewNetworkState) {
  3094. BOOLEAN logEvent = FALSE;
  3095. CLUSTER_EVENT eventCode = 0;
  3096. if (NewNetworkState == ClusterNetworkUnavailable) {
  3097. Network->State = ClusterNetworkUnavailable;
  3098. eventCode = CLUSTER_EVENT_NETWORK_UNAVAILABLE;
  3099. }
  3100. else if (NewNetworkState == ClusterNetworkUp) {
  3101. Network->State = ClusterNetworkUp;
  3102. eventCode = CLUSTER_EVENT_NETWORK_UP;
  3103. logCode = NM_EVENT_CLUSTER_NETWORK_UP;
  3104. logLevel = LOG_NOISE;
  3105. logEvent = TRUE;
  3106. ClRtlLogPrint(LOG_UNUSUAL,
  3107. "[NM] Network %1!ws! (%2!ws!) is up.\n",
  3108. networkId,
  3109. networkName
  3110. );
  3111. }
  3112. else if (NewNetworkState == ClusterNetworkDown) {
  3113. Network->State = ClusterNetworkDown;
  3114. eventCode = CLUSTER_EVENT_NETWORK_DOWN;
  3115. logCode = NM_EVENT_CLUSTER_NETWORK_DOWN;
  3116. logLevel = LOG_UNUSUAL;
  3117. logEvent = TRUE;
  3118. ClRtlLogPrint(LOG_UNUSUAL,
  3119. "[NM] Network %1!ws! (%2!ws!) is down.\n",
  3120. networkId,
  3121. networkName
  3122. );
  3123. }
  3124. else if (NewNetworkState == ClusterNetworkPartitioned) {
  3125. Network->State = ClusterNetworkPartitioned;
  3126. eventCode = CLUSTER_EVENT_NETWORK_PARTITIONED;
  3127. logCode = NM_EVENT_CLUSTER_NETWORK_PARTITIONED;
  3128. logLevel = LOG_UNUSUAL;
  3129. logEvent = TRUE;
  3130. ClRtlLogPrint(LOG_UNUSUAL,
  3131. "[NM] Network %1!ws! (%2!ws!) is partitioned.\n",
  3132. networkId,
  3133. networkName
  3134. );
  3135. }
  3136. else {
  3137. ClRtlLogPrint(LOG_UNUSUAL,
  3138. "[NM] Invalid state %1!u! for network %2!ws!\n",
  3139. Network->State,
  3140. networkId
  3141. );
  3142. CL_ASSERT(FALSE);
  3143. }
  3144. if (eventCode != 0) {
  3145. ClusterEvent(eventCode, Network);
  3146. }
  3147. if (logEvent && (NmpLeaderNodeId == NmLocalNodeId)) {
  3148. CsLogEvent1(
  3149. logLevel,
  3150. logCode,
  3151. networkName
  3152. );
  3153. }
  3154. }
  3155. return;
  3156. } // NmpSetNetworkAndInterfaceStates
  3157. /////////////////////////////////////////////////////////////////////////////
  3158. //
  3159. // Network state management routines
  3160. //
  3161. /////////////////////////////////////////////////////////////////////////////
  3162. VOID
  3163. NmpRecomputeNT5NetworkAndInterfaceStates(
  3164. VOID
  3165. )
  3166. {
  3167. PNM_NETWORK network;
  3168. PLIST_ENTRY entry;
  3169. for (entry = NmpNetworkList.Flink;
  3170. entry != &NmpNetworkList;
  3171. entry = entry->Flink
  3172. )
  3173. {
  3174. network = CONTAINING_RECORD(
  3175. entry,
  3176. NM_NETWORK,
  3177. Linkage
  3178. );
  3179. NmpStartNetworkStateRecalcTimer(
  3180. network,
  3181. NM_NET_STATE_RECALC_TIMEOUT_AFTER_REGROUP
  3182. );
  3183. }
  3184. return;
  3185. } // NmpRecomputeNT5NetworkAndInterfaceStates
  3186. BOOLEAN
  3187. NmpComputeNetworkAndInterfaceStates(
  3188. IN PNM_NETWORK Network,
  3189. IN BOOLEAN IsolateFailure,
  3190. OUT CLUSTER_NETWORK_STATE * NewNetworkState
  3191. )
  3192. /*++
  3193. Routine Description:
  3194. Computes the state of a network and all of its interfaces based on
  3195. connectivity reports from each constituent interface. Attempts
  3196. to distinguish between failures of individual interfaces and
  3197. failure of an entire network.
  3198. Arguments:
  3199. Network - A pointer to the network object to be processed.
  3200. IsolateFailure - Triggers failure isolation analysis if set to true.
  3201. NewNetworkState - A pointer to a variable that, upon return, contains
  3202. the new state of the network.
  3203. Return Value:
  3204. TRUE if either the state of the network or the state of at least one
  3205. of its constituent interfaces changed. FALSE otherwise.
  3206. Notes:
  3207. Called with NmpLock held and the network object referenced.
  3208. --*/
  3209. {
  3210. DWORD numIfUnavailable = 0;
  3211. DWORD numIfFailed = 0;
  3212. DWORD numIfUnreachable = 0;
  3213. DWORD numIfUp = 0;
  3214. DWORD numIfReachable = 0;
  3215. PNM_CONNECTIVITY_MATRIX matrix = Network->ConnectivityMatrix;
  3216. PNM_CONNECTIVITY_MATRIX matrixEntry;
  3217. PNM_STATE_WORK_VECTOR workVector = Network->StateWorkVector;
  3218. DWORD entryCount =
  3219. Network->ConnectivityVector->EntryCount;
  3220. DWORD reporter, ifNetIndex;
  3221. BOOLEAN stateChanged = FALSE;
  3222. LPCWSTR networkId = OmObjectId(Network);
  3223. LPCWSTR netInterfaceId;
  3224. PLIST_ENTRY entry;
  3225. PNM_INTERFACE netInterface;
  3226. NM_STATE_ENTRY state;
  3227. BOOLEAN selfDeclaredFailure = FALSE;
  3228. DWORD interfaceFailureTimeout = 0;
  3229. BOOLEAN abortComputation = FALSE;
  3230. ClRtlLogPrint(LOG_NOISE,
  3231. "[NM] Beginning phase 1 of state computation for network %1!ws!.\n",
  3232. networkId
  3233. );
  3234. //
  3235. // Phase 1 - Compute the state of each interface from the data
  3236. // in the connectivity matrix.
  3237. //
  3238. for ( entry = Network->InterfaceList.Flink;
  3239. entry != &(Network->InterfaceList);
  3240. entry = entry->Flink
  3241. )
  3242. {
  3243. netInterface = CONTAINING_RECORD(
  3244. entry,
  3245. NM_INTERFACE,
  3246. NetworkLinkage
  3247. );
  3248. netInterfaceId = OmObjectId(netInterface);
  3249. ifNetIndex = netInterface->NetIndex;
  3250. workVector[ifNetIndex].ReachableCount = 0;
  3251. if (NmpIsNetworkEnabledForUse(Network)) {
  3252. //
  3253. // First, check what the interface thinks its own state is
  3254. //
  3255. matrixEntry = NM_GET_CONNECTIVITY_MATRIX_ENTRY(
  3256. matrix,
  3257. ifNetIndex,
  3258. ifNetIndex,
  3259. entryCount
  3260. );
  3261. if ( *matrixEntry ==
  3262. (NM_STATE_ENTRY) ClusterNetInterfaceStateUnknown
  3263. )
  3264. {
  3265. //
  3266. // This case should never happen.
  3267. //
  3268. // An existing interface cannot think its own state is
  3269. // unknown. The reflexive entry is always initialized to
  3270. // Unavailable whenever an interface is created.
  3271. //
  3272. ClRtlLogPrint(LOG_NOISE,
  3273. "[NM] No data for interface %1!u! (%2!ws!) on network "
  3274. "%3!ws!\n",
  3275. ifNetIndex,
  3276. netInterfaceId,
  3277. networkId
  3278. );
  3279. CL_ASSERT(
  3280. *matrixEntry !=
  3281. (NM_STATE_ENTRY) ClusterNetInterfaceStateUnknown
  3282. );
  3283. state = ClusterNetInterfaceUnavailable;
  3284. numIfUnavailable++;
  3285. }
  3286. else if ( *matrixEntry ==
  3287. (NM_STATE_ENTRY) ClusterNetInterfaceUnavailable
  3288. )
  3289. {
  3290. if (NM_NODE_UP(netInterface->Node)) {
  3291. //
  3292. // The node is up, but its connectivity report has
  3293. // not been received yet. This case may happen while a
  3294. // node is joining. It can also happen if this node has
  3295. // just become the new leader.
  3296. //
  3297. // Abort the state computation.
  3298. //
  3299. ClRtlLogPrint(LOG_NOISE,
  3300. "[NM] Data is not yet valid for interface %1!u! "
  3301. "(%2!ws!) on network %3!ws!.\n",
  3302. ifNetIndex,
  3303. netInterfaceId,
  3304. networkId
  3305. );
  3306. abortComputation = TRUE;
  3307. break;
  3308. }
  3309. else {
  3310. //
  3311. // The owning node is down or joining.
  3312. // The interface is in the unavailable state.
  3313. //
  3314. ClRtlLogPrint(LOG_NOISE,
  3315. "[NM] Node is down for interface %1!u! (%2!ws!) on "
  3316. "network %3!ws!\n",
  3317. ifNetIndex,
  3318. netInterfaceId,
  3319. networkId
  3320. );
  3321. state = ClusterNetInterfaceUnavailable;
  3322. numIfUnavailable++;
  3323. }
  3324. }
  3325. else if ( *matrixEntry ==
  3326. (NM_STATE_ENTRY) ClusterNetInterfaceFailed
  3327. )
  3328. {
  3329. //
  3330. // The node declared its own interface as failed.
  3331. // The interface is in the failed state.
  3332. //
  3333. ClRtlLogPrint(LOG_NOISE,
  3334. "[NM] Interface %1!u! (%2!ws!) has failed on network "
  3335. "%3!ws!\n",
  3336. ifNetIndex,
  3337. netInterfaceId,
  3338. networkId
  3339. );
  3340. state = ClusterNetInterfaceFailed;
  3341. numIfFailed++;
  3342. if (netInterface->State == ClusterNetInterfaceUp) {
  3343. selfDeclaredFailure = TRUE;
  3344. }
  3345. }
  3346. else {
  3347. CL_ASSERT(
  3348. *matrixEntry == (NM_STATE_ENTRY) ClusterNetInterfaceUp
  3349. );
  3350. //
  3351. // The owning node thinks its interface is Up.
  3352. //
  3353. // If there are no other operational interfaces on the
  3354. // network, then the interface is in the Up state.
  3355. //
  3356. // If there are other operational interfaces on the
  3357. // network, but all of their reports are not yet valid,
  3358. // then we defer calculating a new state for the interface.
  3359. //
  3360. // If there are other operational interfaces on the network,
  3361. // and all of their reports are valid, then if at least one
  3362. // of the operational interfaces reports that the interface
  3363. // is unreachable, then then the interface is in the
  3364. // Unreachable state. If all of the other operational
  3365. // interfaces report that the interface is reachable, then
  3366. // the interface is in the Up state.
  3367. //
  3368. ClRtlLogPrint(LOG_NOISE,
  3369. "[NM] Examining connectivity data for interface %1!u! "
  3370. "(%2!ws!) on network %3!ws!.\n",
  3371. ifNetIndex,
  3372. netInterfaceId,
  3373. networkId
  3374. );
  3375. //
  3376. // Assume that the interface is Up until proven otherwise.
  3377. //
  3378. state = ClusterNetInterfaceUp;
  3379. //
  3380. // Examine the reports from other interfaces -
  3381. // i.e. scan the matrix column - to see if any node with
  3382. // an operational interface reports this interface to
  3383. // be unreachable.
  3384. //
  3385. for (reporter=0; reporter<entryCount; reporter++) {
  3386. if (reporter == ifNetIndex) {
  3387. continue;
  3388. }
  3389. //
  3390. // First, see if the reporting interface is operational
  3391. // by checking what the repoerter thinks of its own
  3392. // interface.
  3393. //
  3394. matrixEntry = NM_GET_CONNECTIVITY_MATRIX_ENTRY(
  3395. matrix,
  3396. reporter,
  3397. reporter,
  3398. entryCount
  3399. );
  3400. if (*matrixEntry == ClusterNetInterfaceUp) {
  3401. PNM_CONNECTIVITY_MATRIX matrixEntry2;
  3402. //
  3403. // Both the reporter and the reportee believe that
  3404. // their respective interfaces are operational.
  3405. // Check if they agree on the state of their
  3406. // connectivity before going any further.
  3407. // ClusNet guarantees that eventually they will
  3408. // agree.
  3409. //
  3410. matrixEntry = NM_GET_CONNECTIVITY_MATRIX_ENTRY(
  3411. matrix,
  3412. reporter,
  3413. ifNetIndex,
  3414. entryCount
  3415. );
  3416. matrixEntry2 = NM_GET_CONNECTIVITY_MATRIX_ENTRY(
  3417. matrix,
  3418. ifNetIndex,
  3419. reporter,
  3420. entryCount
  3421. );
  3422. if (*matrixEntry == *matrixEntry2) {
  3423. //
  3424. // The two interfaces agree on the state of
  3425. // their connectivity. Check what they agree on.
  3426. //
  3427. if (*matrixEntry == ClusterNetInterfaceUp) {
  3428. //
  3429. // The interface is reported to be up.
  3430. //
  3431. ClRtlLogPrint(LOG_NOISE,
  3432. "[NM] Interface %1!u! reports interface "
  3433. "%2!u! is up on network %3!ws!\n",
  3434. reporter,
  3435. ifNetIndex,
  3436. networkId
  3437. );
  3438. workVector[ifNetIndex].ReachableCount++;
  3439. }
  3440. else if ( *matrixEntry ==
  3441. ClusterNetInterfaceUnreachable
  3442. )
  3443. {
  3444. //
  3445. // The interface is reported to be
  3446. // unreachable.
  3447. //
  3448. ClRtlLogPrint(LOG_NOISE,
  3449. "[NM] Interface %1!u! reports interface "
  3450. "%2!u! is unreachable on network %3!ws!\n",
  3451. reporter,
  3452. ifNetIndex,
  3453. networkId
  3454. );
  3455. state = ClusterNetInterfaceUnreachable;
  3456. //
  3457. // If this interface is already in failed state do fault isolation immediately.
  3458. //
  3459. if(workVector[ifNetIndex].State == ClusterNetInterfaceFailed)
  3460. IsolateFailure = TRUE;
  3461. }
  3462. else {
  3463. CL_ASSERT(
  3464. *matrixEntry != ClusterNetInterfaceFailed
  3465. );
  3466. //
  3467. // The interface report is not valid yet.
  3468. // Abort the computation.
  3469. //
  3470. ClRtlLogPrint(LOG_NOISE,
  3471. "[NM] Report from interface %1!u! for "
  3472. "interface %2!u! is not valid yet on "
  3473. "network %3!ws!.\n",
  3474. reporter,
  3475. ifNetIndex,
  3476. networkId
  3477. );
  3478. abortComputation = TRUE;
  3479. break;
  3480. }
  3481. }
  3482. else {
  3483. //
  3484. // The two interfaces do not yet agree on
  3485. // their connectivity. Abort the computation.
  3486. //
  3487. ClRtlLogPrint(LOG_NOISE,
  3488. "[NM] Interface %1!u! and interface %2!u! do "
  3489. "not agree on their connectivity on network "
  3490. "%3!ws!\n",
  3491. reporter,
  3492. ifNetIndex,
  3493. networkId
  3494. );
  3495. abortComputation = TRUE;
  3496. break;
  3497. }
  3498. }
  3499. else {
  3500. //
  3501. // The reporter does not think its own interface is
  3502. // operational.
  3503. //
  3504. ClRtlLogPrint(LOG_NOISE,
  3505. "[NM] The report from interface %1!u! is not "
  3506. "valid on network %2!ws!.\n",
  3507. reporter,
  3508. networkId
  3509. );
  3510. }
  3511. } // end of connectivity matrix scan loop
  3512. if (abortComputation) {
  3513. //
  3514. // Abort Phase 1 computation.
  3515. //
  3516. break;
  3517. }
  3518. if (state == ClusterNetInterfaceUp) {
  3519. ClRtlLogPrint(LOG_NOISE,
  3520. "[NM] Interface %1!u! (%2!ws!) is up on network "
  3521. "%3!ws!.\n",
  3522. ifNetIndex,
  3523. netInterfaceId,
  3524. networkId
  3525. );
  3526. numIfUp++;
  3527. }
  3528. else {
  3529. CL_ASSERT(state == ClusterNetInterfaceUnreachable);
  3530. ClRtlLogPrint(LOG_NOISE,
  3531. "[NM] Interface %1!u! (%2!ws!) is unreachable on "
  3532. "network %3!ws!\n",
  3533. ifNetIndex,
  3534. netInterfaceId,
  3535. networkId
  3536. );
  3537. numIfUnreachable++;
  3538. }
  3539. }
  3540. }
  3541. else {
  3542. //
  3543. // The network is disabled. It is in the Unavailable state.
  3544. //
  3545. ClRtlLogPrint(LOG_NOISE,
  3546. "[NM] Interface %1!u! (%2!ws!) is unavailable because "
  3547. "network %3!ws! is disabled. \n",
  3548. ifNetIndex,
  3549. netInterfaceId,
  3550. networkId
  3551. );
  3552. state = ClusterNetInterfaceUnavailable;
  3553. numIfUnavailable++;
  3554. }
  3555. workVector[ifNetIndex].State = state;
  3556. //
  3557. // Keep track of how many interfaces on the network are
  3558. // reachable by at least one peer.
  3559. //
  3560. if ( (state == ClusterNetInterfaceUp) ||
  3561. (workVector[ifNetIndex].ReachableCount > 0)
  3562. ) {
  3563. numIfReachable++;
  3564. }
  3565. if (netInterface->State != state) {
  3566. stateChanged = TRUE;
  3567. }
  3568. } // end of phase one interface loop
  3569. if (!abortComputation && !IsolateFailure && selfDeclaredFailure) {
  3570. interfaceFailureTimeout =
  3571. NmpGetNetworkInterfaceFailureTimerValue(networkId);
  3572. if (interfaceFailureTimeout > 0) {
  3573. ClRtlLogPrint(LOG_NOISE,
  3574. "[NM] Delaying state computation for network %1!ws! "
  3575. "for %2!u! ms to damp self-declared failure event.\n",
  3576. networkId, interfaceFailureTimeout
  3577. );
  3578. NmpStartNetworkFailureIsolationTimer(
  3579. Network,
  3580. interfaceFailureTimeout
  3581. );
  3582. abortComputation = TRUE;
  3583. }
  3584. }
  3585. if (abortComputation) {
  3586. if (interfaceFailureTimeout == 0) {
  3587. ClRtlLogPrint(LOG_NOISE,
  3588. "[NM] Aborting state computation for network %1!ws! "
  3589. " until connectivity data is valid.\n",
  3590. networkId
  3591. );
  3592. }
  3593. //
  3594. // Undo any changes we made to the work vector.
  3595. //
  3596. for ( entry = Network->InterfaceList.Flink;
  3597. entry != &(Network->InterfaceList);
  3598. entry = entry->Flink
  3599. )
  3600. {
  3601. netInterface = CONTAINING_RECORD(
  3602. entry,
  3603. NM_INTERFACE,
  3604. NetworkLinkage
  3605. );
  3606. ifNetIndex = netInterface->NetIndex;
  3607. workVector[ifNetIndex].State = (NM_STATE_ENTRY)
  3608. netInterface->State;
  3609. }
  3610. *NewNetworkState = Network->State;
  3611. return(FALSE);
  3612. }
  3613. //
  3614. // Phase 2
  3615. //
  3616. // Try to determine the scope of any failures and recompute the
  3617. // interface states. There are two cases in which we can isolate
  3618. // failures.
  3619. //
  3620. // Case 1: Three or more interfaces are operational. At least two
  3621. // interfaces can communicate with a peer. One or more
  3622. // interfaces cannot communicate with any peer.
  3623. // Those that cannot communicate at all have failed.
  3624. //
  3625. // Case 2: Exactly two interfaces are operational and they cannot
  3626. // communicate with one another. If one interface can
  3627. // communicate with an external host while the other
  3628. // cannot communicate with any external host, then the one
  3629. // that cannot communicate has failed.
  3630. //
  3631. // In any other situation, we do nothing.
  3632. //
  3633. ClRtlLogPrint(LOG_NOISE,
  3634. "[NM] Completed phase 1 of state computation for network "
  3635. "%1!ws!.\n",
  3636. networkId
  3637. );
  3638. ClRtlLogPrint(LOG_NOISE,
  3639. "[NM] Unavailable=%1!u!, Failed = %2!u!, Unreachable=%3!u!, "
  3640. "Reachable=%4!u!, Up=%5!u! on network %6!ws! \n",
  3641. numIfUnavailable,
  3642. numIfFailed,
  3643. numIfUnreachable,
  3644. numIfReachable,
  3645. numIfUp,
  3646. networkId
  3647. );
  3648. if (numIfUnreachable > 0) {
  3649. //
  3650. // Some interfaces are unreachable.
  3651. //
  3652. if ( ((numIfUp + numIfUnreachable) >= 3) && (numIfReachable >= 2) ) {
  3653. if (IsolateFailure) {
  3654. //
  3655. // Case 1.
  3656. //
  3657. ClRtlLogPrint(LOG_NOISE,
  3658. "[NM] Trying to determine scope of connectivity failure "
  3659. "for >3 interfaces on network %1!ws!.\n",
  3660. networkId
  3661. );
  3662. //
  3663. // Any operational interface that cannot communicate with at
  3664. // least one other operational interface has failed.
  3665. //
  3666. for ( entry = Network->InterfaceList.Flink;
  3667. entry != &(Network->InterfaceList);
  3668. entry = entry->Flink
  3669. )
  3670. {
  3671. netInterface = CONTAINING_RECORD(
  3672. entry,
  3673. NM_INTERFACE,
  3674. NetworkLinkage
  3675. );
  3676. ifNetIndex = netInterface->NetIndex;
  3677. netInterfaceId = OmObjectId(netInterface);
  3678. if ( ( workVector[ifNetIndex].State ==
  3679. ClusterNetInterfaceUnreachable
  3680. )
  3681. &&
  3682. (workVector[ifNetIndex].ReachableCount == 0)
  3683. )
  3684. {
  3685. ClRtlLogPrint(LOG_NOISE,
  3686. "[NM] Interface %1!u! (%2!ws!) has failed on "
  3687. "network %3!ws!\n",
  3688. ifNetIndex,
  3689. netInterfaceId,
  3690. networkId
  3691. );
  3692. workVector[ifNetIndex].State =
  3693. ClusterNetInterfaceFailed;
  3694. numIfUnreachable--;
  3695. numIfFailed++;
  3696. }
  3697. }
  3698. //
  3699. // If any interface, whose state is still unreachable, can see
  3700. // all other reachable interfaces, change its state to up.
  3701. //
  3702. for ( entry = Network->InterfaceList.Flink;
  3703. entry != &(Network->InterfaceList);
  3704. entry = entry->Flink
  3705. )
  3706. {
  3707. netInterface = CONTAINING_RECORD(
  3708. entry,
  3709. NM_INTERFACE,
  3710. NetworkLinkage
  3711. );
  3712. ifNetIndex = netInterface->NetIndex;
  3713. if ( ( workVector[ifNetIndex].State ==
  3714. ClusterNetInterfaceUnreachable
  3715. )
  3716. &&
  3717. ( workVector[ifNetIndex].ReachableCount ==
  3718. (numIfUp + numIfUnreachable - 1)
  3719. )
  3720. )
  3721. {
  3722. ClRtlLogPrint(LOG_NOISE,
  3723. "[NM] Interface %1!u! (%2!ws!) is up on network "
  3724. "%3!ws!\n",
  3725. ifNetIndex,
  3726. netInterfaceId,
  3727. networkId
  3728. );
  3729. workVector[ifNetIndex].State = ClusterNetInterfaceUp;
  3730. numIfUnreachable--;
  3731. numIfUp++;
  3732. }
  3733. }
  3734. ClRtlLogPrint(LOG_NOISE,
  3735. "[NM] Connectivity failure scope determination complete "
  3736. "for network %1!ws!.\n",
  3737. networkId
  3738. );
  3739. }
  3740. else {
  3741. //
  3742. // Schedule a failure isolation calculation to run later.
  3743. // Declaring a failure can affect cluster resources, so we
  3744. // don't want to do it unless we are sure. Delaying for a
  3745. // while reduces the risk of a false positive.
  3746. //
  3747. NmpStartNetworkFailureIsolationTimer(Network,
  3748. NM_NET_STATE_FAILURE_ISOLATION_TIMEOUT);
  3749. }
  3750. }
  3751. else if ((numIfUnreachable == 2) && (numIfUp == 0)) {
  3752. if (IsolateFailure) {
  3753. //
  3754. // Case 2.
  3755. //
  3756. PNM_INTERFACE interface1 = NULL;
  3757. BOOLEAN interface1HasConnectivity;
  3758. LPCWSTR interfaceId1;
  3759. PNM_INTERFACE interface2 = NULL;
  3760. BOOLEAN interface2HasConnectivity;
  3761. LPCWSTR interfaceId2;
  3762. DWORD status;
  3763. ClRtlLogPrint(LOG_NOISE,
  3764. "[NM] Trying to determine scope of connectivity failure "
  3765. "for 2 interfaces on network %1!ws!.\n",
  3766. networkId
  3767. );
  3768. for ( entry = Network->InterfaceList.Flink;
  3769. entry != &(Network->InterfaceList);
  3770. entry = entry->Flink
  3771. )
  3772. {
  3773. netInterface = CONTAINING_RECORD(
  3774. entry,
  3775. NM_INTERFACE,
  3776. NetworkLinkage
  3777. );
  3778. ifNetIndex = netInterface->NetIndex;
  3779. if ( workVector[ifNetIndex].State ==
  3780. ClusterNetInterfaceUnreachable
  3781. )
  3782. {
  3783. if (interface1 == NULL) {
  3784. interface1 = netInterface;
  3785. interfaceId1 = OmObjectId(interface1);
  3786. ClRtlLogPrint(LOG_NOISE,
  3787. "[NM] Unreachable interface 1 = %1!ws! on "
  3788. "network %2!ws!\n",
  3789. interfaceId1,
  3790. networkId
  3791. );
  3792. }
  3793. else {
  3794. interface2 = netInterface;
  3795. interfaceId2 = OmObjectId(interface2);
  3796. ClRtlLogPrint(LOG_NOISE,
  3797. "[NM] Unreachable interface 2 = %1!ws! on "
  3798. "network %2!ws!\n",
  3799. interfaceId2,
  3800. networkId
  3801. );
  3802. break;
  3803. }
  3804. }
  3805. }
  3806. //
  3807. // NmpTestInterfaceConnectivity releases and reacquires
  3808. // the NmpLock. We must reference the interface objects
  3809. // to ensure that they are still valid upon return from
  3810. // that routine.
  3811. //
  3812. OmReferenceObject(interface1);
  3813. OmReferenceObject(interface2);
  3814. status = NmpTestInterfaceConnectivity(
  3815. interface1,
  3816. &interface1HasConnectivity,
  3817. interface2,
  3818. &interface2HasConnectivity
  3819. );
  3820. if (status == ERROR_SUCCESS) {
  3821. if ( interface1HasConnectivity &&
  3822. !interface2HasConnectivity
  3823. )
  3824. {
  3825. ClRtlLogPrint(LOG_NOISE,
  3826. "[NM] Interface %1!u! (%2!ws!) has Failed on "
  3827. "network %3!ws!\n",
  3828. interface2->NetIndex,
  3829. interfaceId2,
  3830. networkId
  3831. );
  3832. workVector[interface2->NetIndex].State =
  3833. ClusterNetInterfaceFailed;
  3834. numIfUnreachable--;
  3835. numIfFailed++;
  3836. ClRtlLogPrint(LOG_NOISE,
  3837. "[NM] Interface %1!u! (%2!ws!) is Up on network "
  3838. "%3!ws!\n",
  3839. interface1->NetIndex,
  3840. interfaceId1,
  3841. networkId
  3842. );
  3843. workVector[interface1->NetIndex].State =
  3844. ClusterNetInterfaceUp;
  3845. numIfUnreachable--;
  3846. numIfUp++;
  3847. }
  3848. else if ( !interface1HasConnectivity &&
  3849. interface2HasConnectivity
  3850. )
  3851. {
  3852. ClRtlLogPrint(LOG_NOISE,
  3853. "[NM] Interface %1!u! (%2!ws!) has Failed on "
  3854. "network %3!ws!\n",
  3855. interface1->NetIndex,
  3856. interfaceId1,
  3857. networkId
  3858. );
  3859. workVector[interface1->NetIndex].State =
  3860. ClusterNetInterfaceFailed;
  3861. numIfUnreachable--;
  3862. numIfFailed++;
  3863. ClRtlLogPrint(LOG_NOISE,
  3864. "[NM] Interface %1!u! (%2!ws!) is Up on network "
  3865. "%3!ws!\n",
  3866. interface2->NetIndex,
  3867. interfaceId2,
  3868. networkId
  3869. );
  3870. workVector[interface2->NetIndex].State =
  3871. ClusterNetInterfaceUp;
  3872. numIfUnreachable--;
  3873. numIfUp++;
  3874. }
  3875. else {
  3876. ClRtlLogPrint(LOG_UNUSUAL,
  3877. "[NM] Network %1!ws! state is indeterminate, Scheduling"
  3878. " Failure Isolation poll\n",
  3879. networkId
  3880. );
  3881. NmpStartNetworkFailureIsolationTimer(Network,
  3882. NmpGetIsolationPollTimerValue());
  3883. }
  3884. }
  3885. else {
  3886. ClRtlLogPrint(LOG_UNUSUAL,
  3887. "[NM] Error in Interface Connectivity test for Network %1!ws!"
  3888. ", Scheduling Failure Isolation poll\n",
  3889. networkId
  3890. );
  3891. NmpStartNetworkFailureIsolationTimer(Network,
  3892. NmpGetIsolationPollTimerValue());
  3893. }
  3894. OmDereferenceObject(interface1);
  3895. OmDereferenceObject(interface2);
  3896. ClRtlLogPrint(LOG_NOISE,
  3897. "[NM] Connectivity failure scope determination complete "
  3898. "for network %1!ws!.\n",
  3899. networkId
  3900. );
  3901. }
  3902. else {
  3903. //
  3904. // Schedule a failure isolation calculation to run later.
  3905. // Declaring a failure can affect cluster resources, so we
  3906. // don't want to do it unless we are sure. Delaying for a
  3907. // while reduces the risk of a false positive.
  3908. //
  3909. NmpStartNetworkFailureIsolationTimer(Network,
  3910. NM_NET_STATE_FAILURE_ISOLATION_TIMEOUT);
  3911. }
  3912. }
  3913. else {
  3914. ClRtlLogPrint(LOG_NOISE,
  3915. "[NM] Cannot determine scope of connectivity failure on "
  3916. "network %1!ws!.\n",
  3917. networkId
  3918. );
  3919. }
  3920. }
  3921. else {
  3922. //
  3923. // No unreachable interfaces. Disable the failure isolation timer,
  3924. // if it is running.
  3925. //
  3926. Network->FailureIsolationTimer = 0;
  3927. Network->Flags &= ~NM_FLAG_NET_ISOLATE_FAILURE;
  3928. }
  3929. //
  3930. // Phase 3 - Compute the new network state.
  3931. //
  3932. if (numIfUnavailable == Network->InterfaceCount) {
  3933. //
  3934. // All interfaces are unavailable.
  3935. //
  3936. *NewNetworkState = ClusterNetworkUnavailable;
  3937. }
  3938. else if (numIfUnreachable > 0) {
  3939. //
  3940. // Some operational interfaces have experienced
  3941. // a loss of connectivity, but the fault could not be
  3942. // isolated to them.
  3943. //
  3944. if (numIfReachable > 0) {
  3945. CL_ASSERT(numIfReachable >= 2);
  3946. //
  3947. // At least two interfaces can still communicate
  3948. // with each other, so the network is not completely down.
  3949. //
  3950. *NewNetworkState = ClusterNetworkPartitioned;
  3951. }
  3952. else {
  3953. CL_ASSERT(numIfUp == 0);
  3954. //
  3955. // None of the operational interfaces can communicate
  3956. //
  3957. *NewNetworkState = ClusterNetworkDown;
  3958. }
  3959. }
  3960. else if (numIfUp > 0) {
  3961. //
  3962. // Some interfaces are Up, all others are Failed or Unavailable
  3963. //
  3964. *NewNetworkState = ClusterNetworkUp;
  3965. }
  3966. else {
  3967. //
  3968. // Some interfaces are Unavailable, rest are Failed.
  3969. //
  3970. *NewNetworkState = ClusterNetworkDown;
  3971. }
  3972. if (Network->State != *NewNetworkState) {
  3973. stateChanged = TRUE;
  3974. ClRtlLogPrint(LOG_NOISE,
  3975. "[NM] Network %1!ws! is now in state %2!u!\n",
  3976. networkId,
  3977. *NewNetworkState
  3978. );
  3979. }
  3980. return(stateChanged);
  3981. } // NmpComputeNetworkAndInterfaceStates
  3982. DWORD
  3983. NmpGetIsolationPollTimerValue(
  3984. VOID
  3985. )
  3986. /*--
  3987. * Reads the IsolationPollTimerValue Parameter from the registry if it's there
  3988. * else returns default value.
  3989. */
  3990. {
  3991. DWORD value;
  3992. DWORD type;
  3993. DWORD len = sizeof(value);
  3994. DWORD status;
  3995. // Release NM Lock to avoid deadlock with DM lock
  3996. NmpReleaseLock();
  3997. status = DmQueryValue(
  3998. DmClusterParametersKey,
  3999. L"IsolationPollTimerValue",
  4000. &type,
  4001. (LPBYTE)&value,
  4002. &len
  4003. );
  4004. NmpAcquireLock();
  4005. if((status != ERROR_SUCCESS) || (type != REG_DWORD) ||
  4006. (value < 10) || (value > 600000)) {
  4007. ClRtlLogPrint(LOG_UNUSUAL,
  4008. "[NM] Failed to read IsolationPollTimerValue or value out of range,"
  4009. "status %1!u! using default %2!u! ms\n",
  4010. status,
  4011. NM_NET_STATE_FAILURE_ISOLATION_POLL
  4012. );
  4013. return NM_NET_STATE_FAILURE_ISOLATION_POLL;
  4014. }
  4015. else {
  4016. ClRtlLogPrint(LOG_NOISE,
  4017. "[NM] IsolationPollTimerValue = %1!u!\n",
  4018. value
  4019. );
  4020. return value;
  4021. }
  4022. }
  4023. DWORD
  4024. NmpGetNetworkInterfaceFailureTimerValue(
  4025. IN LPCWSTR NetworkId
  4026. )
  4027. /*++
  4028. Routine Description:
  4029. Reads InterfaceFailure timer value from registry.
  4030. If a value is located in the network key, it is used.
  4031. Otherwise the cluster parameters key is checked.
  4032. If no value is present, returns default.
  4033. Arguments:
  4034. NetworkId - id of network whose timer value to determine
  4035. Return value:
  4036. InterfaceFailure timer value
  4037. Notes:
  4038. Called with NM lock held (from NmpComputeNetworkAndInterfaceStates).
  4039. This routine queries the cluster database; hence, it drops the
  4040. NM lock. Since NmpComputeNetworkAndInterfaceStates is always called
  4041. in the context of the NmpWorkerThread, the Network is always
  4042. referenced during execution of this routine.
  4043. --*/
  4044. {
  4045. HDMKEY networkKey, paramKey;
  4046. DWORD status;
  4047. DWORD type;
  4048. DWORD value = NM_NET_STATE_INTERFACE_FAILURE_TIMEOUT;
  4049. DWORD len = sizeof(value);
  4050. BOOLEAN found = FALSE;
  4051. //
  4052. // To avoid deadlock, the DM lock must be acquired before the
  4053. // NM lock. Hence, release the NM lock prior to querying the
  4054. // cluster database.
  4055. //
  4056. NmpReleaseLock();
  4057. //
  4058. // First check the network key
  4059. //
  4060. networkKey = DmOpenKey(DmNetworksKey, NetworkId, KEY_READ);
  4061. if (networkKey == NULL) {
  4062. status = GetLastError();
  4063. ClRtlLogPrint(LOG_UNUSUAL,
  4064. "[NM] Failed to open key for network %1!ws!, "
  4065. "status %1!u!\n",
  4066. NetworkId, status
  4067. );
  4068. }
  4069. else {
  4070. paramKey = DmOpenKey(networkKey, L"Parameters", KEY_READ);
  4071. if (paramKey == NULL) {
  4072. status = GetLastError();
  4073. ClRtlLogPrint(LOG_NOISE,
  4074. "[NM] Failed to find Parameters key "
  4075. "for network %1!ws!, status %2!u!. Checking "
  4076. "cluster parameters ...\n",
  4077. NetworkId, status
  4078. );
  4079. }
  4080. else {
  4081. status = DmQueryValue(
  4082. paramKey,
  4083. L"InterfaceFailureTimeout",
  4084. &type,
  4085. (LPBYTE) &value,
  4086. &len
  4087. );
  4088. if (status != ERROR_SUCCESS) {
  4089. ClRtlLogPrint(LOG_NOISE,
  4090. "[NM] Failed to read InterfaceFailureTimeout "
  4091. "for network %1!ws!, status %2!u!. Checking "
  4092. "cluster parameters ...\n",
  4093. NetworkId, status
  4094. );
  4095. }
  4096. else if (type != REG_DWORD) {
  4097. ClRtlLogPrint(LOG_NOISE,
  4098. "[NM] Unexpected type (%1!u!) for network "
  4099. "%2!ws! InterfaceFailureTimeout, status %3!u!. "
  4100. "Checking cluster parameters ...\n",
  4101. type, NetworkId, status
  4102. );
  4103. }
  4104. else {
  4105. found = TRUE;
  4106. }
  4107. DmCloseKey(paramKey);
  4108. }
  4109. DmCloseKey(networkKey);
  4110. }
  4111. //
  4112. // If no value was found under the network key, check the
  4113. // cluster parameters key.
  4114. //
  4115. if (!found) {
  4116. paramKey = DmOpenKey(DmClusterParametersKey, L"Parameters", KEY_READ);
  4117. if (paramKey == NULL) {
  4118. status = GetLastError();
  4119. ClRtlLogPrint(LOG_NOISE,
  4120. "[NM] Failed to find cluster Parameters key, status %1!u!.\n",
  4121. status
  4122. );
  4123. }
  4124. else {
  4125. status = DmQueryValue(
  4126. paramKey,
  4127. L"InterfaceFailureTimeout",
  4128. &type,
  4129. (LPBYTE) &value,
  4130. &len
  4131. );
  4132. if (status != ERROR_SUCCESS) {
  4133. ClRtlLogPrint(LOG_NOISE,
  4134. "[NM] Failed to read cluster "
  4135. "InterfaceFailureTimeout, status %1!u!. "
  4136. "Using default value ...\n",
  4137. status
  4138. );
  4139. value = NM_NET_STATE_INTERFACE_FAILURE_TIMEOUT;
  4140. }
  4141. else if (type != REG_DWORD) {
  4142. ClRtlLogPrint(LOG_NOISE,
  4143. "[NM] Unexpected type (%1!u!) for cluster "
  4144. "InterfaceFailureTimeout, status %2!u!. "
  4145. "Using default value ...\n",
  4146. type, status
  4147. );
  4148. value = NM_NET_STATE_INTERFACE_FAILURE_TIMEOUT;
  4149. }
  4150. DmCloseKey(paramKey);
  4151. }
  4152. }
  4153. ClRtlLogPrint(LOG_NOISE,
  4154. "[NM] Using InterfaceFailureTimeout of %1!u! ms "
  4155. "for network %2!ws!.\n",
  4156. value, NetworkId
  4157. );
  4158. //
  4159. // Reacquire NM lock.
  4160. //
  4161. NmpAcquireLock();
  4162. return(value);
  4163. }
  4164. VOID
  4165. NmpConnectivityReportWorker(
  4166. IN PCLRTL_WORK_ITEM WorkItem,
  4167. IN DWORD Status,
  4168. IN DWORD BytesTransferred,
  4169. IN ULONG_PTR IoContext
  4170. )
  4171. /*++
  4172. Routine Description:
  4173. Worker routine for deferred operations on network objects.
  4174. Invoked to process items placed in the cluster delayed work queue.
  4175. Arguments:
  4176. WorkItem - Ignored.
  4177. Status - Ignored.
  4178. BytesTransferred - Ignored.
  4179. IoContext - Ignored.
  4180. Return Value:
  4181. None.
  4182. Notes:
  4183. This routine is run in an asynchronous worker thread.
  4184. The NmpActiveThreadCount was incremented when the thread was
  4185. scheduled.
  4186. --*/
  4187. {
  4188. BOOLEAN rescheduled = FALSE;
  4189. NmpAcquireLock();
  4190. ClRtlLogPrint(LOG_NOISE,
  4191. "[NM] Connectivity report worker thread running.\n"
  4192. );
  4193. CL_ASSERT(NmpIsConnectivityReportWorkerRunning == TRUE);
  4194. CL_ASSERT(NmpNeedConnectivityReport == TRUE);
  4195. if (NmpState >= NmStateOnlinePending) {
  4196. PNM_NETWORK network;
  4197. LPCWSTR networkId;
  4198. PLIST_ENTRY entry;
  4199. DWORD status;
  4200. while(TRUE) {
  4201. NmpNeedConnectivityReport = FALSE;
  4202. for (entry = NmpNetworkList.Flink;
  4203. entry != &NmpNetworkList;
  4204. entry = entry->Flink
  4205. )
  4206. {
  4207. network = CONTAINING_RECORD(entry, NM_NETWORK, Linkage);
  4208. if (!NM_DELETE_PENDING(network)) {
  4209. networkId = OmObjectId(network);
  4210. //
  4211. // Deliver an InterfaceFailed event for the local interface
  4212. // if needed.
  4213. //
  4214. if (network->Flags & NM_FLAG_NET_REPORT_LOCAL_IF_FAILED) {
  4215. network->Flags &= ~NM_FLAG_NET_REPORT_LOCAL_IF_FAILED;
  4216. if (NmpIsNetworkRegistered(network)) {
  4217. ClRtlLogPrint(LOG_NOISE,
  4218. "[NM] Processing local interface failed "
  4219. " event for network %1!ws!.\n",
  4220. networkId
  4221. );
  4222. NmpProcessLocalInterfaceStateEvent(
  4223. network->LocalInterface,
  4224. ClusterNetInterfaceFailed
  4225. );
  4226. }
  4227. }
  4228. //
  4229. // Deliver an InterfaceUp event for the local interface
  4230. // if needed.
  4231. //
  4232. if (network->Flags & NM_FLAG_NET_REPORT_LOCAL_IF_UP) {
  4233. network->Flags &= ~NM_FLAG_NET_REPORT_LOCAL_IF_UP;
  4234. if (NmpIsNetworkRegistered(network)) {
  4235. ClRtlLogPrint(LOG_NOISE,
  4236. "[NM] Processing local interface up event "
  4237. "for network %1!ws!.\n",
  4238. networkId
  4239. );
  4240. NmpProcessLocalInterfaceStateEvent(
  4241. network->LocalInterface,
  4242. ClusterNetInterfaceUp
  4243. );
  4244. }
  4245. }
  4246. //
  4247. // Send a connectivity report if needed.
  4248. //
  4249. if (network->Flags & NM_FLAG_NET_REPORT_CONNECTIVITY) {
  4250. CL_NODE_ID leaderNodeId = NmpLeaderNodeId;
  4251. network->Flags &= ~NM_FLAG_NET_REPORT_CONNECTIVITY;
  4252. //
  4253. // Report our connectivity to the leader.
  4254. //
  4255. status = NmpReportNetworkConnectivity(network);
  4256. if (status == ERROR_SUCCESS) {
  4257. //
  4258. // Clear the report retry count.
  4259. //
  4260. network->ConnectivityReportRetryCount = 0;
  4261. }
  4262. else {
  4263. if (NmpLeaderNodeId == leaderNodeId) {
  4264. if (network->ConnectivityReportRetryCount++ <
  4265. NM_CONNECTIVITY_REPORT_RETRY_LIMIT
  4266. )
  4267. {
  4268. //
  4269. // Try again in 500ms.
  4270. //
  4271. network->ConnectivityReportTimer = 500;
  4272. }
  4273. else {
  4274. //
  4275. // We have failed to communicate with
  4276. // the leader for too long. Mutiny.
  4277. //
  4278. NmpAdviseNodeFailure(
  4279. NmpIdArray[NmpLeaderNodeId],
  4280. status
  4281. );
  4282. network->ConnectivityReportRetryCount = 0;
  4283. }
  4284. }
  4285. else {
  4286. //
  4287. // New leader, clear the retry count. We
  4288. // already scheduled another connectivity
  4289. // report in the node down handling.
  4290. //
  4291. network->ConnectivityReportRetryCount = 0;
  4292. }
  4293. }
  4294. }
  4295. }
  4296. } // end network for loop
  4297. if (NmpNeedConnectivityReport == FALSE) {
  4298. //
  4299. // No more work to do - break out of loop.
  4300. //
  4301. break;
  4302. }
  4303. //
  4304. // More work to do. Resubmit the work item. We do this instead
  4305. // of looping so we don't hog the worker thread. If
  4306. // rescheduling fails, we will loop again in this thread.
  4307. //
  4308. ClRtlLogPrint(LOG_NOISE,
  4309. "[NM] More connectivity reports to send. Rescheduling "
  4310. "worker thread.\n"
  4311. );
  4312. status = NmpScheduleConnectivityReportWorker();
  4313. if (status == ERROR_SUCCESS) {
  4314. rescheduled = TRUE;
  4315. break;
  4316. }
  4317. } // end while(TRUE)
  4318. }
  4319. if (!rescheduled) {
  4320. NmpIsConnectivityReportWorkerRunning = FALSE;
  4321. }
  4322. ClRtlLogPrint(LOG_NOISE,
  4323. "[NM] Connectivity report worker thread finished.\n"
  4324. );
  4325. //
  4326. // Decrement active thread reference count.
  4327. //
  4328. NmpLockedLeaveApi();
  4329. NmpReleaseLock();
  4330. return;
  4331. } // NmpConnectivityReportWorker
  4332. VOID
  4333. NmpNetworkWorker(
  4334. IN PCLRTL_WORK_ITEM WorkItem,
  4335. IN DWORD Status,
  4336. IN DWORD BytesTransferred,
  4337. IN ULONG_PTR IoContext
  4338. )
  4339. /*++
  4340. Routine Description:
  4341. Worker routine for deferred operations on network objects.
  4342. Invoked to process items placed in the cluster delayed work queue.
  4343. Arguments:
  4344. WorkItem - A pointer to a work item structure that identifies the
  4345. network for which to perform work.
  4346. Status - Ignored.
  4347. BytesTransferred - Ignored.
  4348. IoContext - Ignored.
  4349. Return Value:
  4350. None.
  4351. Notes:
  4352. This routine is run in an asynchronous worker thread.
  4353. The NmpActiveThreadCount was incremented when the thread was
  4354. scheduled. The network object was also referenced.
  4355. --*/
  4356. {
  4357. PNM_NETWORK network = (PNM_NETWORK) WorkItem->Context;
  4358. LPCWSTR networkId = OmObjectId(network);
  4359. BOOLEAN rescheduled = FALSE;
  4360. NmpAcquireLock();
  4361. ClRtlLogPrint(LOG_NOISE,
  4362. "[NM] Worker thread processing network %1!ws!.\n",
  4363. networkId
  4364. );
  4365. if ((NmpState >= NmStateOnlinePending) && !NM_DELETE_PENDING(network)) {
  4366. DWORD status;
  4367. while(TRUE) {
  4368. CL_ASSERT(network->Flags & NM_FLAG_NET_WORKER_RUNNING);
  4369. //
  4370. // Register the network if needed.
  4371. //
  4372. if (network->Flags & NM_FLAG_NET_NEED_TO_REGISTER) {
  4373. network->Flags &= ~NM_FLAG_NET_NEED_TO_REGISTER;
  4374. if (network->LocalInterface != NULL) {
  4375. (VOID) NmpRegisterNetwork(
  4376. network,
  4377. TRUE // Do retry on failure
  4378. );
  4379. }
  4380. }
  4381. //
  4382. // Isolate a network failure if needed.
  4383. //
  4384. if (network->Flags & NM_FLAG_NET_ISOLATE_FAILURE) {
  4385. BOOLEAN stateChanged;
  4386. CLUSTER_NETWORK_STATE newNetworkState;
  4387. network->Flags &= ~NM_FLAG_NET_ISOLATE_FAILURE;
  4388. //
  4389. // Turn off the state recalc timer and flag, since we will
  4390. // do a recalc here.
  4391. //
  4392. network->Flags &= ~NM_FLAG_NET_RECALC_STATE;
  4393. network->StateRecalcTimer = 0;
  4394. CL_ASSERT(NmpLeaderNodeId == NmLocalNodeId);
  4395. //
  4396. // Recompute the interface and network states
  4397. // with failure isolation enabled.
  4398. //
  4399. stateChanged = NmpComputeNetworkAndInterfaceStates(
  4400. network,
  4401. TRUE,
  4402. &newNetworkState
  4403. );
  4404. if (stateChanged) {
  4405. //
  4406. // Broadcast the new network and interface states to
  4407. // all nodes
  4408. //
  4409. status = NmpGlobalSetNetworkAndInterfaceStates(
  4410. network,
  4411. newNetworkState
  4412. );
  4413. if (status != ERROR_SUCCESS) {
  4414. //
  4415. // Try again in 1 second.
  4416. //
  4417. ClRtlLogPrint(LOG_NOISE,
  4418. "[NM] Global update failed for network %1!ws!, "
  4419. "status %2!u! - restarting failure isolation "
  4420. "timer.\n",
  4421. networkId,
  4422. status
  4423. );
  4424. network->FailureIsolationTimer = 1000;
  4425. }
  4426. }
  4427. }
  4428. //
  4429. // Recalculate the network and interface states if needed.
  4430. //
  4431. if (network->Flags & NM_FLAG_NET_RECALC_STATE) {
  4432. BOOLEAN stateChanged;
  4433. CLUSTER_NETWORK_STATE newNetworkState;
  4434. network->Flags &= ~NM_FLAG_NET_RECALC_STATE;
  4435. CL_ASSERT(NmpLeaderNodeId == NmLocalNodeId);
  4436. //
  4437. // Recompute the interface and network states
  4438. // with failure isolation disabled. It will be
  4439. // enabled if needed.
  4440. //
  4441. stateChanged = NmpComputeNetworkAndInterfaceStates(
  4442. network,
  4443. FALSE,
  4444. &newNetworkState
  4445. );
  4446. if (stateChanged) {
  4447. //
  4448. // Broadcast the new network and interface states to
  4449. // all nodes
  4450. //
  4451. status = NmpGlobalSetNetworkAndInterfaceStates(
  4452. network,
  4453. newNetworkState
  4454. );
  4455. if (status != ERROR_SUCCESS) {
  4456. //
  4457. // Try again in 500ms.
  4458. //
  4459. ClRtlLogPrint(LOG_NOISE,
  4460. "[NM] NetworkStateUpdateWorker failed issue "
  4461. "global update for network %1!ws!, status "
  4462. "%2!u! - restarting update timer.\n",
  4463. networkId,
  4464. status
  4465. );
  4466. network->StateRecalcTimer = 500;
  4467. }
  4468. }
  4469. }
  4470. //
  4471. // Refresh the network multicast configurtion if needed.
  4472. //
  4473. if (network->Flags & NM_FLAG_NET_REFRESH_MCAST) {
  4474. network->Flags &= ~NM_FLAG_NET_REFRESH_MCAST;
  4475. status = NmpRefreshMulticastConfiguration(network);
  4476. if (status != ERROR_SUCCESS) {
  4477. ClRtlLogPrint(LOG_NOISE,
  4478. "[NM] Failed to refresh multicast "
  4479. "configuration for network %1!ws!, "
  4480. "status %2!u!.\n",
  4481. networkId, status
  4482. );
  4483. }
  4484. }
  4485. if (!(network->Flags & NM_NET_WORK_FLAGS)) {
  4486. //
  4487. // No more work to do - break out of loop.
  4488. //
  4489. break;
  4490. }
  4491. //
  4492. // More work to do. Resubmit the work item. We do this instead
  4493. // of looping so we don't hog the worker thread. If
  4494. // rescheduling fails, we will loop again in this thread.
  4495. //
  4496. ClRtlLogPrint(LOG_NOISE,
  4497. "[NM] More work to do for network %1!ws!. Rescheduling "
  4498. "worker thread.\n",
  4499. networkId
  4500. );
  4501. status = NmpScheduleNetworkWorker(network);
  4502. if (status == ERROR_SUCCESS) {
  4503. rescheduled = TRUE;
  4504. break;
  4505. }
  4506. }
  4507. }
  4508. else {
  4509. network->Flags &= ~NM_NET_WORK_FLAGS;
  4510. }
  4511. if (!rescheduled) {
  4512. network->Flags &= ~NM_FLAG_NET_WORKER_RUNNING;
  4513. }
  4514. ClRtlLogPrint(LOG_NOISE,
  4515. "[NM] Worker thread finished processing network %1!ws!.\n",
  4516. networkId
  4517. );
  4518. NmpLockedLeaveApi();
  4519. NmpReleaseLock();
  4520. OmDereferenceObject(network);
  4521. return;
  4522. } // NmpNetworkWorker
  4523. VOID
  4524. NmpNetworkTimerTick(
  4525. IN DWORD MsTickInterval
  4526. )
  4527. /*++
  4528. Routine Description:
  4529. Called by NM periodic timer to decrement network timers.
  4530. Arguments:
  4531. MsTickInterval - The number of milliseconds that have passed since
  4532. the last timer tick.
  4533. Return Value:
  4534. None.
  4535. Notes:
  4536. Called with NmpLock held.
  4537. --*/
  4538. {
  4539. if (NmpLockedEnterApi(NmStateOnlinePending)) {
  4540. PLIST_ENTRY entry;
  4541. PNM_NETWORK network;
  4542. //
  4543. // Walk thru the list of networks and decrement any running timers.
  4544. //
  4545. for ( entry = NmpNetworkList.Flink;
  4546. entry != &NmpNetworkList;
  4547. entry = entry->Flink
  4548. )
  4549. {
  4550. network = CONTAINING_RECORD(entry, NM_NETWORK, Linkage);
  4551. //
  4552. // Network registration retry timer.
  4553. //
  4554. if (network->RegistrationRetryTimer != 0) {
  4555. if (network->RegistrationRetryTimer > MsTickInterval) {
  4556. network->RegistrationRetryTimer -= MsTickInterval;
  4557. }
  4558. else {
  4559. //
  4560. // The timer has expired. Schedule a worker thread
  4561. // to register the network.
  4562. //
  4563. LPCWSTR networkId = OmObjectId(network);
  4564. LPCWSTR networkName = OmObjectName(network);
  4565. ClRtlLogPrint(LOG_NOISE,
  4566. "[NM] Registration retry timer expired for "
  4567. "network %1!ws! (%2!ws!).\n",
  4568. networkId,
  4569. networkName
  4570. );
  4571. NmpScheduleNetworkRegistration(network);
  4572. }
  4573. }
  4574. //
  4575. // Connectivity report generation timer.
  4576. //
  4577. if (network->ConnectivityReportTimer != 0) {
  4578. if (network->ConnectivityReportTimer > MsTickInterval) {
  4579. network->ConnectivityReportTimer -= MsTickInterval;
  4580. }
  4581. else {
  4582. //
  4583. // The timer has expired. Schedule a worker thread
  4584. // to deliver a connectivity report.
  4585. //
  4586. LPCWSTR networkId = OmObjectId(network);
  4587. LPCWSTR networkName = OmObjectName(network);
  4588. ClRtlLogPrint(LOG_NOISE,
  4589. "[NM] Connectivity report timer expired for "
  4590. "network %1!ws! (%2!ws!).\n",
  4591. networkId,
  4592. networkName
  4593. );
  4594. NmpScheduleNetworkConnectivityReport(network);
  4595. }
  4596. }
  4597. //
  4598. // Network state recalculation timer.
  4599. //
  4600. if (network->StateRecalcTimer != 0) {
  4601. if (network->StateRecalcTimer > MsTickInterval) {
  4602. network->StateRecalcTimer -= MsTickInterval;
  4603. }
  4604. else {
  4605. //
  4606. // The timer has expired. Schedule a worker thread
  4607. // to recalculate the state of the network.
  4608. //
  4609. LPCWSTR networkId = OmObjectId(network);
  4610. LPCWSTR networkName = OmObjectName(network);
  4611. ClRtlLogPrint(LOG_NOISE,
  4612. "[NM] State recalculation timer expired for "
  4613. "network %1!ws! (%2!ws!).\n",
  4614. networkId,
  4615. networkName
  4616. );
  4617. NmpScheduleNetworkStateRecalc(network);
  4618. }
  4619. }
  4620. //
  4621. // Network multicast address renewal timer.
  4622. //
  4623. if (network->McastAddressRenewTimer != 0) {
  4624. if (network->McastAddressRenewTimer > MsTickInterval) {
  4625. network->McastAddressRenewTimer -= MsTickInterval;
  4626. }
  4627. else {
  4628. //
  4629. // The timer has expired. Schedule a worker thread
  4630. // to renew the network's multicast address.
  4631. //
  4632. LPCWSTR networkId = OmObjectId(network);
  4633. LPCWSTR networkName = OmObjectName(network);
  4634. ClRtlLogPrint(LOG_NOISE,
  4635. "[NM] Multicast address lease renewal timer "
  4636. "expired for network %1!ws! (%2!ws!).\n",
  4637. networkId,
  4638. networkName
  4639. );
  4640. NmpScheduleMulticastAddressRenewal(network);
  4641. }
  4642. }
  4643. //
  4644. // Network multicast address release timer.
  4645. //
  4646. if (network->McastAddressReleaseRetryTimer != 0) {
  4647. if (network->McastAddressReleaseRetryTimer > MsTickInterval) {
  4648. network->McastAddressReleaseRetryTimer -= MsTickInterval;
  4649. }
  4650. else {
  4651. //
  4652. // The timer has expired. Schedule a worker thread
  4653. // to release the network's multicast address.
  4654. //
  4655. LPCWSTR networkId = OmObjectId(network);
  4656. LPCWSTR networkName = OmObjectName(network);
  4657. ClRtlLogPrint(LOG_NOISE,
  4658. "[NM] Multicast address release timer "
  4659. "expired for network %1!ws! (%2!ws!).\n",
  4660. networkId,
  4661. networkName
  4662. );
  4663. NmpScheduleMulticastAddressRelease(network);
  4664. }
  4665. }
  4666. //
  4667. // Network multicast reconfiguration timer.
  4668. //
  4669. if (network->McastAddressReconfigureRetryTimer != 0) {
  4670. if (network->McastAddressReconfigureRetryTimer > MsTickInterval) {
  4671. network->McastAddressReconfigureRetryTimer -= MsTickInterval;
  4672. }
  4673. else {
  4674. //
  4675. // The timer has expired. Schedule a worker thread
  4676. // to recreate the network's multicast configuration.
  4677. //
  4678. LPCWSTR networkId = OmObjectId(network);
  4679. LPCWSTR networkName = OmObjectName(network);
  4680. ClRtlLogPrint(LOG_NOISE,
  4681. "[NM] Multicast reconfiguration timer "
  4682. "expired for network %1!ws! (%2!ws!).\n",
  4683. networkId,
  4684. networkName
  4685. );
  4686. NmpScheduleMulticastReconfiguration(network);
  4687. }
  4688. }
  4689. //
  4690. // Network multicast configuration refresh timer.
  4691. //
  4692. if (network->McastAddressRefreshRetryTimer != 0) {
  4693. if (network->McastAddressRefreshRetryTimer > MsTickInterval) {
  4694. network->McastAddressRefreshRetryTimer -= MsTickInterval;
  4695. }
  4696. else {
  4697. //
  4698. // The timer has expired. Schedule a worker thread
  4699. // to refresh the network's multicast configuration.
  4700. //
  4701. LPCWSTR networkId = OmObjectId(network);
  4702. LPCWSTR networkName = OmObjectName(network);
  4703. ClRtlLogPrint(LOG_NOISE,
  4704. "[NM] Multicast address refresh timer "
  4705. "expired for network %1!ws! (%2!ws!).\n",
  4706. networkId,
  4707. networkName
  4708. );
  4709. NmpScheduleMulticastRefresh(network);
  4710. }
  4711. }
  4712. //
  4713. // Network failure isolation timer.
  4714. //
  4715. if (network->FailureIsolationTimer != 0) {
  4716. if (network->FailureIsolationTimer > MsTickInterval) {
  4717. network->FailureIsolationTimer -= MsTickInterval;
  4718. }
  4719. else {
  4720. //
  4721. // The timer has expired. Schedule a worker thread
  4722. // to perform failure isolation on the network.
  4723. //
  4724. DWORD status = ERROR_SUCCESS;
  4725. LPCWSTR networkId = OmObjectId(network);
  4726. LPCWSTR networkName = OmObjectName(network);
  4727. ClRtlLogPrint(LOG_NOISE,
  4728. "[NM] Failure isolation timer expired for network "
  4729. "%1!ws! (%2!ws!).\n",
  4730. networkId,
  4731. networkName
  4732. );
  4733. if (!NmpIsNetworkWorkerRunning(network)) {
  4734. status = NmpScheduleNetworkWorker(network);
  4735. }
  4736. //
  4737. // Zero out the timer if we succeeded in scheduling a
  4738. // worker thread. If we failed, leave the timer value
  4739. // non-zero and we'll try again on the next tick.
  4740. //
  4741. if (status == ERROR_SUCCESS) {
  4742. network->FailureIsolationTimer = 0;
  4743. network->Flags |= NM_FLAG_NET_ISOLATE_FAILURE;
  4744. }
  4745. }
  4746. }
  4747. //
  4748. // Network name change pending timer.
  4749. //
  4750. if (network->NameChangePendingTimer != 0) {
  4751. if (network->NameChangePendingTimer > MsTickInterval) {
  4752. network->NameChangePendingTimer -= MsTickInterval;
  4753. }
  4754. else {
  4755. LPCWSTR networkId = OmObjectId(network);
  4756. LPCWSTR networkName = OmObjectName(network);
  4757. ClRtlLogPrint(LOG_NOISE,
  4758. "[NM] Name change pending timer expired for network "
  4759. "%1!ws! (%2!ws!).\n",
  4760. networkId,
  4761. networkName
  4762. );
  4763. // Clear the name change pending flag
  4764. network->Flags &= ~NM_FLAG_NET_NAME_CHANGE_PENDING;
  4765. }
  4766. }
  4767. //
  4768. // Network multicast key regenerate timer.
  4769. //
  4770. if (network->McastKeyRegenerateTimer != 0) {
  4771. if (network->McastKeyRegenerateTimer > MsTickInterval) {
  4772. // test
  4773. LPCWSTR networkId = OmObjectId(network);
  4774. LPCWSTR networkName = OmObjectName(network);
  4775. // test
  4776. network->McastKeyRegenerateTimer -= MsTickInterval;
  4777. }
  4778. else {
  4779. //
  4780. // The timer has expired. Schedule a worker thread
  4781. // to regenerate the network's multicast key.
  4782. //
  4783. LPCWSTR networkId = OmObjectId(network);
  4784. LPCWSTR networkName = OmObjectName(network);
  4785. ClRtlLogPrint(LOG_NOISE,
  4786. "[NM] Multicast key regenerate timer "
  4787. "expired for network %1!ws! (%2!ws!).\n",
  4788. networkId,
  4789. networkName
  4790. );
  4791. NmpScheduleMulticastKeyRegeneration(network);
  4792. }
  4793. }
  4794. }
  4795. NmpLockedLeaveApi();
  4796. }
  4797. return;
  4798. } // NmpNetworkTimerTick
  4799. VOID
  4800. NmpStartNetworkConnectivityReportTimer(
  4801. PNM_NETWORK Network
  4802. )
  4803. /*++
  4804. Routine Description:
  4805. Starts the connectivity report timer for a network. Connectivity
  4806. reports are delayed in order to aggregate events when a failure
  4807. occurs that affects multiple nodes.
  4808. Arguments:
  4809. Network - A pointer to the network for which to start the timer.
  4810. Return Value
  4811. None.
  4812. Notes:
  4813. Called with NM lock held.
  4814. --*/
  4815. {
  4816. //
  4817. // Check if the timer is already running.
  4818. //
  4819. if (Network->ConnectivityReportTimer == 0) {
  4820. //
  4821. // Check how many nodes are attached to this network.
  4822. //
  4823. if (Network->InterfaceCount <= 2) {
  4824. //
  4825. // There is no point in waiting to aggregate reports when
  4826. // only two nodes are connected to the network.
  4827. // Just schedule a worker thread to deliver the report.
  4828. //
  4829. NmpScheduleNetworkConnectivityReport(Network);
  4830. }
  4831. else {
  4832. //
  4833. // More than two nodes are connected to this network.
  4834. // Start the timer.
  4835. //
  4836. LPCWSTR networkId = OmObjectId(Network);
  4837. LPCWSTR networkName = OmObjectName(Network);
  4838. Network->ConnectivityReportTimer =
  4839. NM_NET_CONNECTIVITY_REPORT_TIMEOUT;
  4840. ClRtlLogPrint(LOG_NOISE,
  4841. "[NM] Started connectivity report timer (%1!u!ms) for "
  4842. "network %2!ws! (%3!ws!)\n",
  4843. Network->ConnectivityReportTimer,
  4844. networkId,
  4845. networkName
  4846. );
  4847. }
  4848. }
  4849. return;
  4850. } // NmpStartNetworkConnectivityReportTimer
  4851. VOID
  4852. NmpStartNetworkStateRecalcTimer(
  4853. PNM_NETWORK Network,
  4854. DWORD Timeout
  4855. )
  4856. {
  4857. LPCWSTR networkId = OmObjectId(Network);
  4858. LPCWSTR networkName = OmObjectName(Network);
  4859. if (Network->StateRecalcTimer == 0) {
  4860. Network->StateRecalcTimer = Timeout;
  4861. ClRtlLogPrint(LOG_NOISE,
  4862. "[NM] Started state recalculation timer (%1!u!ms) for "
  4863. "network %2!ws! (%3!ws!)\n",
  4864. Network->StateRecalcTimer,
  4865. networkId,
  4866. networkName
  4867. );
  4868. }
  4869. return;
  4870. } // NmpStartNetworkStateRecalcTimer
  4871. VOID
  4872. NmpStartNetworkFailureIsolationTimer(
  4873. PNM_NETWORK Network,
  4874. DWORD Timeout
  4875. )
  4876. {
  4877. if (Network->FailureIsolationTimer == 0) {
  4878. Network->FailureIsolationTimer = Timeout;
  4879. ClRtlLogPrint(LOG_NOISE,
  4880. "[NM] Started failure isolation timer (%1!u!ms) for "
  4881. "network %2!ws! (%3!ws!)\n",
  4882. Network->FailureIsolationTimer,
  4883. OmObjectId(Network),
  4884. OmObjectName(Network)
  4885. );
  4886. }
  4887. return;
  4888. } // NmpStartNetworkFailureIsolationTimer
  4889. VOID
  4890. NmpStartNetworkRegistrationRetryTimer(
  4891. PNM_NETWORK Network
  4892. )
  4893. {
  4894. if (Network->RegistrationRetryTimer == 0) {
  4895. if (Network->RegistrationRetryTimeout == 0) {
  4896. Network->RegistrationRetryTimeout =
  4897. NM_NET_MIN_REGISTRATION_RETRY_TIMEOUT;
  4898. }
  4899. else {
  4900. //
  4901. // Exponential backoff
  4902. //
  4903. Network->RegistrationRetryTimeout *= 2;
  4904. if ( Network->RegistrationRetryTimeout >
  4905. NM_NET_MAX_REGISTRATION_RETRY_TIMEOUT
  4906. )
  4907. {
  4908. Network->RegistrationRetryTimeout =
  4909. NM_NET_MAX_REGISTRATION_RETRY_TIMEOUT;
  4910. }
  4911. }
  4912. Network->RegistrationRetryTimer = Network->RegistrationRetryTimeout;
  4913. ClRtlLogPrint(LOG_NOISE,
  4914. "[NM] Started registration retry timer (%1!u!ms) for "
  4915. "network %2!ws! (%3!ws!)\n",
  4916. Network->RegistrationRetryTimer,
  4917. OmObjectId(Network),
  4918. OmObjectName(Network)
  4919. );
  4920. }
  4921. return;
  4922. } // NmpStartNetworkRegistrationRetryTimer
  4923. VOID
  4924. NmpStartNetworkNameChangePendingTimer(
  4925. IN PNM_NETWORK Network,
  4926. IN DWORD Timeout
  4927. )
  4928. {
  4929. if (Network->NameChangePendingTimer != Timeout) {
  4930. Network->NameChangePendingTimer = Timeout;
  4931. ClRtlLogPrint(LOG_NOISE,
  4932. "[NM] %1!ws! name change pending timer (%2!u!ms) for "
  4933. "network %3!ws! (%4!ws!)\n",
  4934. ((Timeout != 0) ? L"Started" : L"Cleared"),
  4935. Network->NameChangePendingTimer,
  4936. OmObjectId(Network),
  4937. OmObjectName(Network)
  4938. );
  4939. }
  4940. return;
  4941. } // NmpStartNetworkNameChangePendingTimer
  4942. VOID
  4943. NmpScheduleNetworkConnectivityReport(
  4944. PNM_NETWORK Network
  4945. )
  4946. /*++
  4947. Routine Description:
  4948. Schedules a worker thread to deliver a connectivity report to
  4949. the leader node for the specified network. Called when the
  4950. ConnectivityReport timer expires for a network. Also called
  4951. directly in some cases.
  4952. Arguments:
  4953. A pointer to the network object for which to generate a report.
  4954. Return Value:
  4955. None.
  4956. Notes:
  4957. This routine is called with the NM lock held.
  4958. --*/
  4959. {
  4960. DWORD status = ERROR_SUCCESS;
  4961. //
  4962. // Check if a worker thread is already scheduled.
  4963. //
  4964. if (!NmpIsConnectivityReportWorkerRunning) {
  4965. status = NmpScheduleConnectivityReportWorker();
  4966. }
  4967. if (status == ERROR_SUCCESS) {
  4968. //
  4969. // We succeeded in scheduling a worker thread. Stop the
  4970. // ConnectivityReport timer and set the work flag to generate
  4971. // a report.
  4972. //
  4973. Network->ConnectivityReportTimer = 0;
  4974. Network->Flags |= NM_FLAG_NET_REPORT_CONNECTIVITY;
  4975. NmpNeedConnectivityReport = TRUE;
  4976. }
  4977. else {
  4978. //
  4979. // We failed to schedule a worker thread. Set the
  4980. // ConnecivityReport timer to expire on the next tick, so we
  4981. // can try again.
  4982. //
  4983. Network->ConnectivityReportTimer = 1;
  4984. }
  4985. return;
  4986. } // NmpScheduleNetworkConnectivityReport
  4987. VOID
  4988. NmpScheduleNetworkStateRecalc(
  4989. PNM_NETWORK Network
  4990. )
  4991. /*++
  4992. Routine Description:
  4993. Schedules a worker thread to recalculate the state of the
  4994. specified network and all of the network's interface. A network
  4995. state recalculation can be triggered by the arrival of a connectivity
  4996. report, the joining/death of a node, or a network role change.
  4997. Arguments:
  4998. A pointer to the network object whose state is to be recalculated.
  4999. Return Value:
  5000. None.
  5001. Notes:
  5002. This routine is called with the NM lock held.
  5003. --*/
  5004. {
  5005. DWORD status = ERROR_SUCCESS;
  5006. //
  5007. // Check if a worker thread is already scheduled to
  5008. // service this network.
  5009. //
  5010. if (!NmpIsNetworkWorkerRunning(Network)) {
  5011. status = NmpScheduleNetworkWorker(Network);
  5012. }
  5013. if (status == ERROR_SUCCESS) {
  5014. //
  5015. // We succeeded in scheduling a worker thread. Stop the
  5016. // StateRecalc timer and set the state recalculation work flag.
  5017. //
  5018. Network->StateRecalcTimer = 0;
  5019. Network->Flags |= NM_FLAG_NET_RECALC_STATE;
  5020. }
  5021. else {
  5022. //
  5023. // We failed to schedule a worker thread. Set the StateRecalc
  5024. // timer to expire on the next tick, so we can try again.
  5025. //
  5026. Network->ConnectivityReportTimer = 1;
  5027. }
  5028. return;
  5029. } // NmpScheduleNetworkStateRecalc
  5030. VOID
  5031. NmpScheduleNetworkRegistration(
  5032. PNM_NETWORK Network
  5033. )
  5034. /*++
  5035. Routine Description:
  5036. Schedules a worker thread to register a network with the cluster
  5037. transport.
  5038. Arguments:
  5039. A pointer to the network to register.
  5040. Return Value:
  5041. None.
  5042. Notes:
  5043. This routine is called with the NM lock held.
  5044. --*/
  5045. {
  5046. DWORD status = ERROR_SUCCESS;
  5047. //
  5048. // Check if a worker thread is already scheduled to
  5049. // service this network.
  5050. //
  5051. if (!NmpIsNetworkWorkerRunning(Network)) {
  5052. status = NmpScheduleNetworkWorker(Network);
  5053. }
  5054. if (status == ERROR_SUCCESS) {
  5055. //
  5056. // We succeeded in scheduling a worker thread. Stop the
  5057. // retry timer and set the registration work flag.
  5058. //
  5059. Network->RegistrationRetryTimer = 0;
  5060. Network->Flags |= NM_FLAG_NET_NEED_TO_REGISTER;
  5061. }
  5062. else {
  5063. //
  5064. // We failed to schedule a worker thread. Set the retry
  5065. // timer to expire on the next tick, so we can try again.
  5066. //
  5067. Network->RegistrationRetryTimer = 1;
  5068. }
  5069. return;
  5070. } // NmpScheduleNetworkRegistration
  5071. DWORD
  5072. NmpScheduleConnectivityReportWorker(
  5073. VOID
  5074. )
  5075. /*++
  5076. Routine Description:
  5077. Schedule a worker thread to deliver network connectivity reports.
  5078. Arguments:
  5079. None.
  5080. Return Value:
  5081. A Win32 status code.
  5082. Notes:
  5083. Called with the NM global lock held.
  5084. --*/
  5085. {
  5086. DWORD status;
  5087. ClRtlInitializeWorkItem(
  5088. &NmpConnectivityReportWorkItem,
  5089. NmpConnectivityReportWorker,
  5090. NULL
  5091. );
  5092. status = ClRtlPostItemWorkQueue(
  5093. CsDelayedWorkQueue,
  5094. &NmpConnectivityReportWorkItem,
  5095. 0,
  5096. 0
  5097. );
  5098. if (status == ERROR_SUCCESS) {
  5099. NmpActiveThreadCount++;
  5100. NmpIsConnectivityReportWorkerRunning = TRUE;
  5101. ClRtlLogPrint(LOG_NOISE,
  5102. "[NM] Scheduled network connectivity report worker thread.\n"
  5103. );
  5104. }
  5105. else {
  5106. ClRtlLogPrint(LOG_UNUSUAL,
  5107. "[NM] Failed to schedule network connectivity report worker "
  5108. "thread, status %1!u!\n",
  5109. status
  5110. );
  5111. }
  5112. return(status);
  5113. } // NmpScheduleConnectivityReportWorker
  5114. DWORD
  5115. NmpScheduleNetworkWorker(
  5116. PNM_NETWORK Network
  5117. )
  5118. /*++
  5119. Routine Description:
  5120. Schedule a worker thread to service this network
  5121. Arguments:
  5122. Network - Pointer to the network for which to schedule a worker thread.
  5123. Return Value:
  5124. A Win32 status code.
  5125. Notes:
  5126. Called with the NM global lock held.
  5127. --*/
  5128. {
  5129. DWORD status;
  5130. LPCWSTR networkId = OmObjectId(Network);
  5131. ClRtlInitializeWorkItem(
  5132. &(Network->WorkItem),
  5133. NmpNetworkWorker,
  5134. (PVOID) Network
  5135. );
  5136. status = ClRtlPostItemWorkQueue(
  5137. CsDelayedWorkQueue,
  5138. &(Network->WorkItem),
  5139. 0,
  5140. 0
  5141. );
  5142. if (status == ERROR_SUCCESS) {
  5143. ClRtlLogPrint(LOG_NOISE,
  5144. "[NM] Scheduled worker thread to service network %1!ws!.\n",
  5145. networkId
  5146. );
  5147. NmpActiveThreadCount++;
  5148. Network->Flags |= NM_FLAG_NET_WORKER_RUNNING;
  5149. OmReferenceObject(Network);
  5150. }
  5151. else {
  5152. ClRtlLogPrint(LOG_UNUSUAL,
  5153. "[NM] Failed to schedule worker thread to service network "
  5154. "%1!ws!, status %2!u!\n",
  5155. networkId,
  5156. status
  5157. );
  5158. }
  5159. return(status);
  5160. } // NmpScheduleNetworkWorker
  5161. DWORD
  5162. NmpReportNetworkConnectivity(
  5163. IN PNM_NETWORK Network
  5164. )
  5165. /*+
  5166. Notes:
  5167. Called with the NmpLock held.
  5168. May be called by asynchronous worker threads.
  5169. --*/
  5170. {
  5171. DWORD status = ERROR_SUCCESS;
  5172. LPCWSTR networkId = OmObjectId(Network);
  5173. //
  5174. // Since this routine is called by asynchronous worker threads,
  5175. // check if the report is still valid.
  5176. //
  5177. if (NmpIsNetworkRegistered(Network)) {
  5178. PNM_CONNECTIVITY_VECTOR vector = Network->ConnectivityVector;
  5179. PNM_INTERFACE localInterface = Network->LocalInterface;
  5180. //
  5181. // Record the information in our local data structures.
  5182. //
  5183. ClRtlLogPrint(LOG_UNUSUAL,
  5184. "[NM] Updating local connectivity info for network %1!ws!.\n",
  5185. networkId
  5186. );
  5187. NmpProcessInterfaceConnectivityReport(
  5188. localInterface,
  5189. vector
  5190. );
  5191. if (NmpLeaderNodeId != NmLocalNodeId) {
  5192. //
  5193. // Send the report to the leader via RPC.
  5194. //
  5195. PNM_CONNECTIVITY_VECTOR tmpVector;
  5196. DWORD vectorSize;
  5197. LPCWSTR localInterfaceId =
  5198. OmObjectId(localInterface);
  5199. //
  5200. // Allocate a temporary connectivity vector, since the
  5201. // one in the network object can be resized during the
  5202. // RPC call.
  5203. //
  5204. vectorSize = sizeof(NM_CONNECTIVITY_VECTOR) +
  5205. ((vector->EntryCount - 1) * sizeof(NM_STATE_ENTRY));
  5206. tmpVector = LocalAlloc(LMEM_FIXED, vectorSize);
  5207. if (tmpVector != NULL) {
  5208. CopyMemory(tmpVector, vector, vectorSize);
  5209. OmReferenceObject(Network);
  5210. OmReferenceObject(localInterface);
  5211. if (NM_NODE_UP(NmLocalNode) && (NmpState == NmStateOnline)) {
  5212. //
  5213. // This node is fully operational. Send the report
  5214. // directly to the leader.
  5215. //
  5216. PNM_NODE node = NmpIdArray[NmpLeaderNodeId];
  5217. RPC_BINDING_HANDLE rpcBinding = node->ReportRpcBinding;
  5218. OmReferenceObject(node);
  5219. status = NmpReportInterfaceConnectivity(
  5220. rpcBinding,
  5221. (LPWSTR) localInterfaceId,
  5222. tmpVector,
  5223. (LPWSTR) networkId
  5224. );
  5225. OmDereferenceObject(node);
  5226. }
  5227. else if (CsJoinSponsorBinding != NULL) {
  5228. //
  5229. // This node is joining. Forward the report to the
  5230. // sponsor.
  5231. //
  5232. ClRtlLogPrint(LOG_UNUSUAL,
  5233. "[NM] Reporting connectivity to sponsor for "
  5234. "network %1!ws!.\n",
  5235. networkId
  5236. );
  5237. NmpReleaseLock();
  5238. status = NmRpcReportJoinerInterfaceConnectivity(
  5239. CsJoinSponsorBinding,
  5240. NmpJoinSequence,
  5241. NmLocalNodeIdString,
  5242. (LPWSTR) localInterfaceId,
  5243. tmpVector
  5244. );
  5245. NmpAcquireLock();
  5246. }
  5247. else {
  5248. //
  5249. // This node must be shutting down
  5250. //
  5251. CL_ASSERT(NmpState == NmStateOfflinePending);
  5252. status = ERROR_SUCCESS;
  5253. }
  5254. if (status != ERROR_SUCCESS) {
  5255. ClRtlLogPrint(LOG_NOISE,
  5256. "[NM] Failed to report connectivity for network "
  5257. "%1!ws!, status %2!u!.\n",
  5258. networkId,
  5259. status
  5260. );
  5261. }
  5262. LocalFree(tmpVector);
  5263. OmDereferenceObject(localInterface);
  5264. OmDereferenceObject(Network);
  5265. }
  5266. else {
  5267. status = ERROR_NOT_ENOUGH_MEMORY;
  5268. }
  5269. }
  5270. }
  5271. return(status);
  5272. } // NmpReportNetworkConnectivity
  5273. VOID
  5274. NmpUpdateNetworkConnectivityForDownNode(
  5275. PNM_NODE Node
  5276. )
  5277. /*++
  5278. Notes:
  5279. Called with NmpLock held.
  5280. --*/
  5281. {
  5282. PLIST_ENTRY entry;
  5283. PNM_NETWORK network;
  5284. LPCWSTR networkId;
  5285. PNM_INTERFACE netInterface;
  5286. DWORD entryCount;
  5287. DWORD i;
  5288. PNM_CONNECTIVITY_MATRIX matrixEntry;
  5289. ClRtlLogPrint(LOG_NOISE,
  5290. "[NM] Cleaning up network and interface states for dead node %1!u!\n",
  5291. Node->NodeId
  5292. );
  5293. //
  5294. // Walk the dead node's interface list and clean up the network and
  5295. // interface states.
  5296. //
  5297. for (entry = Node->InterfaceList.Flink;
  5298. entry != &(Node->InterfaceList);
  5299. entry = entry->Flink
  5300. )
  5301. {
  5302. netInterface = CONTAINING_RECORD(
  5303. entry,
  5304. NM_INTERFACE,
  5305. NodeLinkage
  5306. );
  5307. network = netInterface->Network;
  5308. networkId = OmObjectId(network);
  5309. ClRtlLogPrint(LOG_NOISE,
  5310. "[NM] Cleaning up state of network %1!ws!\n",
  5311. networkId
  5312. );
  5313. //
  5314. // Invalidate the connectivity data for this interface.
  5315. //
  5316. NmpSetInterfaceConnectivityData(
  5317. network,
  5318. netInterface->NetIndex,
  5319. ClusterNetInterfaceUnavailable
  5320. );
  5321. //
  5322. // If the local node is attached to the network, schedule a
  5323. // connectivity report to the new leader.
  5324. //
  5325. if (NmpIsNetworkRegistered(network)) {
  5326. NmpScheduleNetworkConnectivityReport(network);
  5327. }
  5328. //
  5329. // If the local node is the (possibly new) leader, schedule
  5330. // a state update. We explicitly enable this timer here in case
  5331. // there are no active nodes attached to the network.
  5332. //
  5333. if (NmpLeaderNodeId == NmLocalNodeId) {
  5334. NmpStartNetworkStateRecalcTimer(
  5335. network,
  5336. NM_NET_STATE_RECALC_TIMEOUT_AFTER_REGROUP
  5337. );
  5338. }
  5339. }
  5340. return;
  5341. } // NmpUpdateNetworkConnectivityForDownNode
  5342. VOID
  5343. NmpFreeNetworkStateEnum(
  5344. PNM_NETWORK_STATE_ENUM NetworkStateEnum
  5345. )
  5346. {
  5347. PNM_NETWORK_STATE_INFO networkStateInfo;
  5348. DWORD i;
  5349. for (i=0; i<NetworkStateEnum->NetworkCount; i++) {
  5350. networkStateInfo = &(NetworkStateEnum->NetworkList[i]);
  5351. if (networkStateInfo->Id != NULL) {
  5352. MIDL_user_free(networkStateInfo->Id);
  5353. }
  5354. }
  5355. MIDL_user_free(NetworkStateEnum);
  5356. return;
  5357. } // NmpFreeNetworkStateEnum
  5358. /////////////////////////////////////////////////////////////////////////////
  5359. //
  5360. // Database management routines
  5361. //
  5362. /////////////////////////////////////////////////////////////////////////////
  5363. DWORD
  5364. NmpCreateNetworkDefinition(
  5365. IN PNM_NETWORK_INFO NetworkInfo,
  5366. IN HLOCALXSACTION Xaction
  5367. )
  5368. /*++
  5369. Routine Description:
  5370. Creates a new network definition in the cluster database.
  5371. Arguments:
  5372. NetworkInfo - A pointer to the information structure describing the
  5373. network to create.
  5374. Return Value:
  5375. ERROR_SUCCESS if successful.
  5376. A Win32 error code otherwise.
  5377. --*/
  5378. {
  5379. DWORD status;
  5380. HDMKEY networkKey = NULL;
  5381. DWORD valueLength;
  5382. DWORD disposition;
  5383. ClRtlLogPrint(LOG_NOISE,
  5384. "[NM] Creating database entry for network %1!ws!\n",
  5385. NetworkInfo->Id
  5386. );
  5387. networkKey = DmLocalCreateKey(
  5388. Xaction,
  5389. DmNetworksKey,
  5390. NetworkInfo->Id,
  5391. 0,
  5392. KEY_WRITE,
  5393. NULL,
  5394. &disposition
  5395. );
  5396. if (networkKey == NULL) {
  5397. status = GetLastError();
  5398. ClRtlLogPrint(LOG_CRITICAL,
  5399. "[NM] Failed to create network key, status %1!u!\n",
  5400. status
  5401. );
  5402. return(status);
  5403. }
  5404. CL_ASSERT(disposition == REG_CREATED_NEW_KEY);
  5405. //
  5406. // Write the name value for this network
  5407. //
  5408. valueLength = (wcslen(NetworkInfo->Name) + 1) * sizeof(WCHAR);
  5409. status = DmLocalSetValue(
  5410. Xaction,
  5411. networkKey,
  5412. CLUSREG_NAME_NET_NAME,
  5413. REG_SZ,
  5414. (CONST BYTE *) NetworkInfo->Name,
  5415. valueLength
  5416. );
  5417. if (status != ERROR_SUCCESS) {
  5418. ClRtlLogPrint(LOG_CRITICAL,
  5419. "[NM] Set of network name value failed, status %1!u!.\n",
  5420. status
  5421. );
  5422. goto error_exit;
  5423. }
  5424. //
  5425. // Write the description value for this network
  5426. //
  5427. valueLength = (wcslen(NetworkInfo->Description) + 1) * sizeof(WCHAR);
  5428. status = DmLocalSetValue(
  5429. Xaction,
  5430. networkKey,
  5431. CLUSREG_NAME_NET_DESC,
  5432. REG_SZ,
  5433. (CONST BYTE *) NetworkInfo->Description,
  5434. valueLength
  5435. );
  5436. if (status != ERROR_SUCCESS) {
  5437. ClRtlLogPrint(LOG_CRITICAL,
  5438. "[NM] Set of network description value failed, status %1!u!.\n",
  5439. status
  5440. );
  5441. goto error_exit;
  5442. }
  5443. //
  5444. // Write the role value for this network
  5445. //
  5446. status = DmLocalSetValue(
  5447. Xaction,
  5448. networkKey,
  5449. CLUSREG_NAME_NET_ROLE,
  5450. REG_DWORD,
  5451. (CONST BYTE *) &(NetworkInfo->Role),
  5452. sizeof(DWORD)
  5453. );
  5454. if (status != ERROR_SUCCESS) {
  5455. ClRtlLogPrint(LOG_CRITICAL,
  5456. "[NM] Set of network role value failed, status %1!u!.\n",
  5457. status
  5458. );
  5459. goto error_exit;
  5460. }
  5461. //
  5462. // Write the priority value for this network
  5463. //
  5464. status = DmLocalSetValue(
  5465. Xaction,
  5466. networkKey,
  5467. CLUSREG_NAME_NET_PRIORITY,
  5468. REG_DWORD,
  5469. (CONST BYTE *) &(NetworkInfo->Priority),
  5470. sizeof(DWORD)
  5471. );
  5472. if (status != ERROR_SUCCESS) {
  5473. ClRtlLogPrint(LOG_CRITICAL,
  5474. "[NM] Set of network priority value failed, status %1!u!.\n",
  5475. status
  5476. );
  5477. goto error_exit;
  5478. }
  5479. //
  5480. // Write the transport value for this network
  5481. //
  5482. valueLength = (wcslen(NetworkInfo->Transport) + 1) * sizeof(WCHAR);
  5483. status = DmLocalSetValue(
  5484. Xaction,
  5485. networkKey,
  5486. CLUSREG_NAME_NET_TRANSPORT,
  5487. REG_SZ,
  5488. (CONST BYTE *) NetworkInfo->Transport,
  5489. valueLength
  5490. );
  5491. if (status != ERROR_SUCCESS) {
  5492. ClRtlLogPrint(LOG_CRITICAL,
  5493. "[NM] Set of network transport value failed, status %1!u!.\n",
  5494. status
  5495. );
  5496. goto error_exit;
  5497. }
  5498. //
  5499. // Write the address value for this network
  5500. //
  5501. valueLength = (wcslen(NetworkInfo->Address) + 1) * sizeof(WCHAR);
  5502. status = DmLocalSetValue(
  5503. Xaction,
  5504. networkKey,
  5505. CLUSREG_NAME_NET_ADDRESS,
  5506. REG_SZ,
  5507. (CONST BYTE *) NetworkInfo->Address,
  5508. valueLength
  5509. );
  5510. if (status != ERROR_SUCCESS) {
  5511. ClRtlLogPrint(LOG_CRITICAL,
  5512. "[NM] Set of network address value failed, status %1!u!.\n",
  5513. status
  5514. );
  5515. goto error_exit;
  5516. }
  5517. //
  5518. // Write the address mask value for this network
  5519. //
  5520. valueLength = (wcslen(NetworkInfo->AddressMask) + 1) * sizeof(WCHAR);
  5521. status = DmLocalSetValue(
  5522. Xaction,
  5523. networkKey,
  5524. CLUSREG_NAME_NET_ADDRESS_MASK,
  5525. REG_SZ,
  5526. (CONST BYTE *) NetworkInfo->AddressMask,
  5527. valueLength
  5528. );
  5529. if (status != ERROR_SUCCESS) {
  5530. ClRtlLogPrint(LOG_CRITICAL,
  5531. "[NM] Set of network address mask value failed, status %1!u!.\n",
  5532. status
  5533. );
  5534. goto error_exit;
  5535. }
  5536. CL_ASSERT(status == ERROR_SUCCESS);
  5537. error_exit:
  5538. if (networkKey != NULL) {
  5539. DmCloseKey(networkKey);
  5540. }
  5541. return(status);
  5542. } // NmpCreateNetworkDefinition
  5543. DWORD
  5544. NmpSetNetworkNameDefinition(
  5545. IN PNM_NETWORK_INFO NetworkInfo,
  5546. IN HLOCALXSACTION Xaction
  5547. )
  5548. /*++
  5549. Routine Description:
  5550. Changes the network name in the local database
  5551. Arguments:
  5552. NetworkInfo - A pointer to the information structure describing the
  5553. network to create.
  5554. Return Value:
  5555. ERROR_SUCCESS if successful.
  5556. A Win32 error code otherwise.
  5557. --*/
  5558. {
  5559. DWORD status;
  5560. HDMKEY networkKey = NULL;
  5561. DWORD disposition;
  5562. ClRtlLogPrint(LOG_NOISE,
  5563. "[NM] Changing network name database entry for network %1!ws!\n",
  5564. NetworkInfo->Id
  5565. );
  5566. //
  5567. // Open the network's key.
  5568. //
  5569. networkKey = DmOpenKey(DmNetworksKey, NetworkInfo->Id, KEY_WRITE);
  5570. if (networkKey == NULL) {
  5571. status = GetLastError();
  5572. ClRtlLogPrint(LOG_CRITICAL,
  5573. "[NM] Failed to open network key, status %1!u!\n",
  5574. status
  5575. );
  5576. goto error_exit;
  5577. }
  5578. //
  5579. // Write the name value for this network
  5580. //
  5581. status = DmLocalSetValue(
  5582. Xaction,
  5583. networkKey,
  5584. CLUSREG_NAME_NET_NAME,
  5585. REG_SZ,
  5586. (CONST BYTE *) NetworkInfo->Name,
  5587. NM_WCSLEN( NetworkInfo->Name )
  5588. );
  5589. if (status != ERROR_SUCCESS) {
  5590. ClRtlLogPrint(LOG_CRITICAL,
  5591. "[NM] Set of network name value failed, status %1!u!.\n",
  5592. status
  5593. );
  5594. goto error_exit;
  5595. }
  5596. CL_ASSERT(status == ERROR_SUCCESS);
  5597. error_exit:
  5598. if (networkKey != NULL) {
  5599. DmCloseKey(networkKey);
  5600. }
  5601. return(status);
  5602. } // NmpSetNetworkNameDefinition
  5603. DWORD
  5604. NmpGetNetworkDefinition(
  5605. IN LPWSTR NetworkId,
  5606. OUT PNM_NETWORK_INFO NetworkInfo
  5607. )
  5608. /*++
  5609. Routine Description:
  5610. Reads information about a defined cluster network from the cluster
  5611. database and fills in a structure describing it.
  5612. Arguments:
  5613. NetworkId - A pointer to a unicode string containing the ID of the
  5614. network to query.
  5615. NetworkInfo - A pointer to the network info structure to fill in.
  5616. Return Value:
  5617. ERROR_SUCCESS if the routine succeeds.
  5618. A Win32 error code otherwise.
  5619. --*/
  5620. {
  5621. DWORD status;
  5622. HDMKEY networkKey = NULL;
  5623. DWORD valueLength, valueSize;
  5624. DWORD i;
  5625. ZeroMemory(NetworkInfo, sizeof(NM_NETWORK_INFO));
  5626. //
  5627. // Open the network's key.
  5628. //
  5629. networkKey = DmOpenKey(DmNetworksKey, NetworkId, KEY_READ);
  5630. if (networkKey == NULL) {
  5631. status = GetLastError();
  5632. ClRtlLogPrint(LOG_CRITICAL,
  5633. "[NM] Failed to open network key, status %1!u!\n",
  5634. status
  5635. );
  5636. goto error_exit;
  5637. }
  5638. //
  5639. // Copy the ID value.
  5640. //
  5641. NetworkInfo->Id = MIDL_user_allocate(NM_WCSLEN(NetworkId));
  5642. if (NetworkInfo->Id == NULL) {
  5643. status = ERROR_NOT_ENOUGH_MEMORY;
  5644. goto error_exit;
  5645. }
  5646. wcscpy(NetworkInfo->Id, NetworkId);
  5647. //
  5648. // Read the network's name.
  5649. //
  5650. valueLength = 0;
  5651. status = NmpQueryString(
  5652. networkKey,
  5653. CLUSREG_NAME_NET_NAME,
  5654. REG_SZ,
  5655. &(NetworkInfo->Name),
  5656. &valueLength,
  5657. &valueSize
  5658. );
  5659. if (status != ERROR_SUCCESS) {
  5660. ClRtlLogPrint(LOG_CRITICAL,
  5661. "[NM] Query of name value failed for network %1!ws!, "
  5662. "status %2!u!.\n",
  5663. NetworkId,
  5664. status
  5665. );
  5666. goto error_exit;
  5667. }
  5668. //
  5669. // Read the description value.
  5670. //
  5671. valueLength = 0;
  5672. status = NmpQueryString(
  5673. networkKey,
  5674. CLUSREG_NAME_NET_DESC,
  5675. REG_SZ,
  5676. &(NetworkInfo->Description),
  5677. &valueLength,
  5678. &valueSize
  5679. );
  5680. if (status != ERROR_SUCCESS) {
  5681. ClRtlLogPrint(LOG_CRITICAL,
  5682. "[NM] Query of description value failed for network %1!ws!, "
  5683. "status %2!u!.\n",
  5684. NetworkId,
  5685. status
  5686. );
  5687. goto error_exit;
  5688. }
  5689. //
  5690. // Read the role value.
  5691. //
  5692. status = DmQueryDword(
  5693. networkKey,
  5694. CLUSREG_NAME_NET_ROLE,
  5695. &(NetworkInfo->Role),
  5696. NULL
  5697. );
  5698. if (status != ERROR_SUCCESS) {
  5699. ClRtlLogPrint(LOG_CRITICAL,
  5700. "[NM] Query of role value failed for network %1!ws!, "
  5701. "status %2!u!.\n",
  5702. NetworkId,
  5703. status
  5704. );
  5705. goto error_exit;
  5706. }
  5707. //
  5708. // Read the priority value.
  5709. //
  5710. status = DmQueryDword(
  5711. networkKey,
  5712. CLUSREG_NAME_NET_PRIORITY,
  5713. &(NetworkInfo->Priority),
  5714. NULL
  5715. );
  5716. if (status != ERROR_SUCCESS) {
  5717. ClRtlLogPrint(LOG_CRITICAL,
  5718. "[NM] Query of priority value failed for network %1!ws!, "
  5719. "status %2!u!.\n",
  5720. NetworkId,
  5721. status
  5722. );
  5723. goto error_exit;
  5724. }
  5725. //
  5726. // Read the address value.
  5727. //
  5728. valueLength = 0;
  5729. status = NmpQueryString(
  5730. networkKey,
  5731. CLUSREG_NAME_NET_ADDRESS,
  5732. REG_SZ,
  5733. &(NetworkInfo->Address),
  5734. &valueLength,
  5735. &valueSize
  5736. );
  5737. if (status != ERROR_SUCCESS) {
  5738. ClRtlLogPrint(LOG_CRITICAL,
  5739. "[NM] Query of address value failed for network %1!ws!, "
  5740. "status %2!u!.\n",
  5741. NetworkId,
  5742. status
  5743. );
  5744. goto error_exit;
  5745. }
  5746. //
  5747. // Read the address mask.
  5748. //
  5749. valueLength = 0;
  5750. status = NmpQueryString(
  5751. networkKey,
  5752. CLUSREG_NAME_NET_ADDRESS_MASK,
  5753. REG_SZ,
  5754. &(NetworkInfo->AddressMask),
  5755. &valueLength,
  5756. &valueSize
  5757. );
  5758. if (status != ERROR_SUCCESS) {
  5759. ClRtlLogPrint(LOG_CRITICAL,
  5760. "[NM] Query of address mask value failed for network %1!ws!, "
  5761. "status %2!u!.\n",
  5762. NetworkId,
  5763. status
  5764. );
  5765. goto error_exit;
  5766. }
  5767. //
  5768. // Read the transport name.
  5769. //
  5770. valueLength = 0;
  5771. status = NmpQueryString(
  5772. networkKey,
  5773. CLUSREG_NAME_NET_TRANSPORT,
  5774. REG_SZ,
  5775. &(NetworkInfo->Transport),
  5776. &valueLength,
  5777. &valueSize
  5778. );
  5779. if (status != ERROR_SUCCESS) {
  5780. ClRtlLogPrint(LOG_CRITICAL,
  5781. "[NM] Query of transport value failed for network %1!ws!, "
  5782. "status %2!u!.\n",
  5783. NetworkId,
  5784. status
  5785. );
  5786. goto error_exit;
  5787. }
  5788. CL_ASSERT(status == ERROR_SUCCESS);
  5789. error_exit:
  5790. if (status != ERROR_SUCCESS) {
  5791. ClNetFreeNetworkInfo(NetworkInfo);
  5792. }
  5793. if (networkKey != NULL) {
  5794. DmCloseKey(networkKey);
  5795. }
  5796. return(status);
  5797. } // NmpGetNetworkDefinition
  5798. DWORD
  5799. NmpEnumNetworkDefinitions(
  5800. OUT PNM_NETWORK_ENUM * NetworkEnum
  5801. )
  5802. /*++
  5803. Routine Description:
  5804. Reads information about defined cluster networks from the cluster
  5805. database. and builds an enumeration structure to hold the information.
  5806. Arguments:
  5807. NetworkEnum - A pointer to the variable into which to place a pointer to
  5808. the allocated network enumeration.
  5809. Return Value:
  5810. ERROR_SUCCESS if the routine succeeds.
  5811. A Win32 error code otherwise.
  5812. --*/
  5813. {
  5814. DWORD status;
  5815. PNM_NETWORK_ENUM networkEnum = NULL;
  5816. PNM_NETWORK_INFO networkInfo;
  5817. WCHAR networkId[CS_NETWORK_ID_LENGTH + 1];
  5818. DWORD i;
  5819. DWORD valueLength;
  5820. DWORD numNetworks;
  5821. DWORD ignored;
  5822. FILETIME fileTime;
  5823. *NetworkEnum = NULL;
  5824. //
  5825. // First count the number of networks.
  5826. //
  5827. status = DmQueryInfoKey(
  5828. DmNetworksKey,
  5829. &numNetworks,
  5830. &ignored, // MaxSubKeyLen
  5831. &ignored, // Values
  5832. &ignored, // MaxValueNameLen
  5833. &ignored, // MaxValueLen
  5834. &ignored, // lpcbSecurityDescriptor
  5835. &fileTime
  5836. );
  5837. if (status != ERROR_SUCCESS) {
  5838. ClRtlLogPrint(LOG_CRITICAL,
  5839. "[NM] Failed to query Networks key information, status %1!u!\n",
  5840. status
  5841. );
  5842. return(status);
  5843. }
  5844. if (numNetworks == 0) {
  5845. valueLength = sizeof(NM_NETWORK_ENUM);
  5846. }
  5847. else {
  5848. valueLength = sizeof(NM_NETWORK_ENUM) +
  5849. (sizeof(NM_NETWORK_INFO) * (numNetworks-1));
  5850. }
  5851. valueLength = sizeof(NM_NETWORK_ENUM) +
  5852. (sizeof(NM_NETWORK_INFO) * (numNetworks-1));
  5853. networkEnum = MIDL_user_allocate(valueLength);
  5854. if (networkEnum == NULL) {
  5855. ClRtlLogPrint(LOG_CRITICAL, "[NM] Failed to allocate memory.\n");
  5856. return(ERROR_NOT_ENOUGH_MEMORY);
  5857. }
  5858. ZeroMemory(networkEnum, valueLength);
  5859. for (i=0; i < numNetworks; i++) {
  5860. networkInfo = &(networkEnum->NetworkList[i]);
  5861. valueLength = sizeof(networkId);
  5862. status = DmEnumKey(
  5863. DmNetworksKey,
  5864. i,
  5865. &(networkId[0]),
  5866. &valueLength,
  5867. NULL
  5868. );
  5869. if (status != ERROR_SUCCESS) {
  5870. ClRtlLogPrint(LOG_CRITICAL,
  5871. "[NM] Failed to enumerate network key, status %1!u!\n",
  5872. status
  5873. );
  5874. goto error_exit;
  5875. }
  5876. status = NmpGetNetworkDefinition(networkId, networkInfo);
  5877. if (status != ERROR_SUCCESS) {
  5878. goto error_exit;
  5879. }
  5880. networkEnum->NetworkCount++;
  5881. }
  5882. *NetworkEnum = networkEnum;
  5883. return(ERROR_SUCCESS);
  5884. error_exit:
  5885. if (networkEnum != NULL) {
  5886. ClNetFreeNetworkEnum(networkEnum);
  5887. }
  5888. return(status);
  5889. }
  5890. /////////////////////////////////////////////////////////////////////////////
  5891. //
  5892. // Object management routines
  5893. //
  5894. /////////////////////////////////////////////////////////////////////////////
  5895. DWORD
  5896. NmpCreateNetworkObjects(
  5897. IN PNM_NETWORK_ENUM NetworkEnum
  5898. )
  5899. /*++
  5900. Routine Description:
  5901. Processes a network information enumeration and creates network objects.
  5902. Arguments:
  5903. NetworkEnum - A pointer to a network information enumeration structure.
  5904. Return Value:
  5905. ERROR_SUCCESS if the routine completes successfully.
  5906. A Win32 error code otherwise.
  5907. --*/
  5908. {
  5909. DWORD status = ERROR_SUCCESS;
  5910. PNM_NETWORK_INFO networkInfo;
  5911. PNM_NETWORK network;
  5912. DWORD i;
  5913. for (i=0; i < NetworkEnum->NetworkCount; i++) {
  5914. networkInfo = &(NetworkEnum->NetworkList[i]);
  5915. network = NmpCreateNetworkObject(networkInfo);
  5916. if (network == NULL) {
  5917. status = GetLastError();
  5918. ClRtlLogPrint(LOG_CRITICAL,
  5919. "[NM] Failed to create network %1!ws!, status %2!u!.\n",
  5920. networkInfo->Id,
  5921. status
  5922. );
  5923. break;
  5924. }
  5925. else {
  5926. OmDereferenceObject(network);
  5927. }
  5928. }
  5929. return(status);
  5930. } // NmpCreateNetworkObjects
  5931. PNM_NETWORK
  5932. NmpCreateNetworkObject(
  5933. IN PNM_NETWORK_INFO NetworkInfo
  5934. )
  5935. /*++
  5936. Routine Description:
  5937. Instantiates a cluster network object.
  5938. Arguments:
  5939. NetworkInfo - A pointer to a structure describing the network to create.
  5940. Return Value:
  5941. A pointer to the new network object on success.
  5942. NULL on failure.
  5943. --*/
  5944. {
  5945. DWORD status;
  5946. PNM_NETWORK network = NULL;
  5947. BOOL created = FALSE;
  5948. DWORD i;
  5949. ClRtlLogPrint(LOG_NOISE,
  5950. "[NM] Creating object for network %1!ws! (%2!ws!).\n",
  5951. NetworkInfo->Id,
  5952. NetworkInfo->Name
  5953. );
  5954. //
  5955. // Make sure that an object with the same name doesn't already exist.
  5956. //
  5957. network = OmReferenceObjectById(ObjectTypeNetwork, NetworkInfo->Id);
  5958. if (network != NULL) {
  5959. OmDereferenceObject(network);
  5960. ClRtlLogPrint(LOG_CRITICAL,
  5961. "[NM] A network object named %1!ws! already exists. Cannot "
  5962. "create a new network with the same name.\n",
  5963. NetworkInfo->Id
  5964. );
  5965. SetLastError(ERROR_OBJECT_ALREADY_EXISTS);
  5966. return(NULL);
  5967. }
  5968. //
  5969. // Ensure that the IP (sub)network is unique in the cluster. Two
  5970. // nodes can race to create a new network in some cases.
  5971. //
  5972. // [RajDas] Need to check mask too for uniqueness.
  5973. network = NmpReferenceNetworkByAddress(
  5974. NetworkInfo->Address,
  5975. NetworkInfo->AddressMask
  5976. );
  5977. if (network != NULL) {
  5978. OmDereferenceObject(network);
  5979. ClRtlLogPrint(LOG_CRITICAL,
  5980. "[NM] A network object already exists for IP network %1!ws!. "
  5981. "Cannot create a new network with the same address.\n",
  5982. NetworkInfo->Address
  5983. );
  5984. SetLastError(ERROR_OBJECT_ALREADY_EXISTS);
  5985. return(NULL);
  5986. }
  5987. //
  5988. // Create a network object.
  5989. //
  5990. network = OmCreateObject(
  5991. ObjectTypeNetwork,
  5992. NetworkInfo->Id,
  5993. NetworkInfo->Name,
  5994. &created
  5995. );
  5996. if (network == NULL) {
  5997. status = GetLastError();
  5998. ClRtlLogPrint(LOG_CRITICAL,
  5999. "[NM] Failed to create object for network %1!ws! (%2!ws!), status %3!u!\n",
  6000. NetworkInfo->Id,
  6001. NetworkInfo->Name,
  6002. status
  6003. );
  6004. goto error_exit;
  6005. }
  6006. CL_ASSERT(created == TRUE);
  6007. //
  6008. // Initialize the network object
  6009. //
  6010. ZeroMemory(network, sizeof(NM_NETWORK));
  6011. network->ShortId = InterlockedIncrement(&NmpNextNetworkShortId);
  6012. network->State = ClusterNetworkUnavailable;
  6013. network->Role = NetworkInfo->Role;
  6014. network->Priority = NetworkInfo->Priority;
  6015. network->Description = NetworkInfo->Description;
  6016. NetworkInfo->Description = NULL;
  6017. network->Transport = NetworkInfo->Transport;
  6018. NetworkInfo->Transport = NULL;
  6019. network->Address = NetworkInfo->Address;
  6020. NetworkInfo->Address = NULL;
  6021. network->AddressMask = NetworkInfo->AddressMask;
  6022. NetworkInfo->AddressMask = NULL;
  6023. InitializeListHead(&(network->InterfaceList));
  6024. InitializeListHead(&(network->McastAddressReleaseList));
  6025. //
  6026. // Allocate an initial connectivity vector.
  6027. // Note that we get one vector entry as part of
  6028. // the NM_CONNECTIVITY_VECTOR structure.
  6029. //
  6030. #define NM_INITIAL_VECTOR_SIZE 2
  6031. network->ConnectivityVector = LocalAlloc(
  6032. LMEM_FIXED,
  6033. ( sizeof(NM_CONNECTIVITY_VECTOR) +
  6034. ( ((NM_INITIAL_VECTOR_SIZE) - 1) *
  6035. sizeof(NM_STATE_ENTRY)
  6036. )
  6037. ));
  6038. if (network->ConnectivityVector == NULL) {
  6039. status = ERROR_NOT_ENOUGH_MEMORY;
  6040. ClRtlLogPrint(LOG_CRITICAL,
  6041. "[NM] Failed to allocate memory for connectivity vector\n"
  6042. );
  6043. goto error_exit;
  6044. }
  6045. network->ConnectivityVector->EntryCount = NM_INITIAL_VECTOR_SIZE;
  6046. FillMemory(
  6047. &(network->ConnectivityVector->Data[0]),
  6048. NM_INITIAL_VECTOR_SIZE * sizeof(NM_STATE_ENTRY),
  6049. (UCHAR) ClusterNetInterfaceStateUnknown
  6050. );
  6051. //
  6052. // Allocate a state work vector
  6053. //
  6054. network->StateWorkVector = LocalAlloc(
  6055. LMEM_FIXED,
  6056. (NM_INITIAL_VECTOR_SIZE) *
  6057. sizeof(NM_STATE_WORK_ENTRY)
  6058. );
  6059. if (network->StateWorkVector == NULL) {
  6060. status = ERROR_NOT_ENOUGH_MEMORY;
  6061. ClRtlLogPrint(LOG_CRITICAL,
  6062. "[NM] Failed to allocate memory for state work vector\n"
  6063. );
  6064. goto error_exit;
  6065. }
  6066. //
  6067. // Initialize the state work vector
  6068. //
  6069. for (i=0; i<NM_INITIAL_VECTOR_SIZE; i++) {
  6070. network->StateWorkVector[i].State =
  6071. (NM_STATE_ENTRY) ClusterNetInterfaceStateUnknown;
  6072. }
  6073. //
  6074. // Put a reference on the object for the caller.
  6075. //
  6076. OmReferenceObject(network);
  6077. NmpAcquireLock();
  6078. //
  6079. // Allocate the corresponding connectivity matrix
  6080. //
  6081. network->ConnectivityMatrix =
  6082. LocalAlloc(
  6083. LMEM_FIXED,
  6084. NM_SIZEOF_CONNECTIVITY_MATRIX(NM_INITIAL_VECTOR_SIZE)
  6085. );
  6086. if (network->ConnectivityMatrix == NULL) {
  6087. status = ERROR_NOT_ENOUGH_MEMORY;
  6088. NmpReleaseLock();
  6089. OmDereferenceObject(network);
  6090. ClRtlLogPrint(LOG_CRITICAL,
  6091. "[NM] Failed to allocate memory for connectivity matrix\n"
  6092. );
  6093. goto error_exit;
  6094. }
  6095. //
  6096. // Initialize the matrix
  6097. //
  6098. FillMemory(
  6099. network->ConnectivityMatrix,
  6100. NM_SIZEOF_CONNECTIVITY_MATRIX(NM_INITIAL_VECTOR_SIZE),
  6101. (UCHAR) ClusterNetInterfaceStateUnknown
  6102. );
  6103. //
  6104. // Make the network object available.
  6105. //
  6106. InsertTailList(&NmpNetworkList, &(network->Linkage));
  6107. NmpNetworkCount++;
  6108. if (NmpIsNetworkForInternalUse(network)) {
  6109. NmpInsertInternalNetwork(network);
  6110. NmpInternalNetworkCount++;
  6111. }
  6112. if (NmpIsNetworkForClientAccess(network)) {
  6113. NmpClientNetworkCount++;
  6114. }
  6115. network->Flags |= NM_FLAG_OM_INSERTED;
  6116. OmInsertObject(network);
  6117. NmpReleaseLock();
  6118. return(network);
  6119. error_exit:
  6120. if (network != NULL) {
  6121. NmpAcquireLock();
  6122. NmpDeleteNetworkObject(network, FALSE);
  6123. NmpReleaseLock();
  6124. }
  6125. SetLastError(status);
  6126. return(NULL);
  6127. } // NmpCreateNetworkObject
  6128. DWORD
  6129. NmpGetNetworkObjectInfo(
  6130. IN PNM_NETWORK Network,
  6131. OUT PNM_NETWORK_INFO NetworkInfo
  6132. )
  6133. /*++
  6134. Routine Description:
  6135. Reads information about a defined cluster network from the
  6136. network object and fills in a structure describing it.
  6137. Arguments:
  6138. Network - A pointer to the network object to query.
  6139. NetworkInfo - A pointer to the structure to fill in with network
  6140. information.
  6141. Return Value:
  6142. ERROR_SUCCESS if the routine succeeds.
  6143. A Win32 error code otherwise.
  6144. Notes:
  6145. Called with NmpLock held.
  6146. --*/
  6147. {
  6148. DWORD status = ERROR_NOT_ENOUGH_MEMORY;
  6149. LPWSTR tmpString = NULL;
  6150. LPWSTR networkId = (LPWSTR) OmObjectId(Network);
  6151. LPWSTR networkName = (LPWSTR) OmObjectName(Network);
  6152. ZeroMemory(NetworkInfo, sizeof(NM_NETWORK_INFO));
  6153. tmpString = MIDL_user_allocate(NM_WCSLEN(networkId));
  6154. if (tmpString == NULL) {
  6155. goto error_exit;
  6156. }
  6157. wcscpy(tmpString, networkId);
  6158. NetworkInfo->Id = tmpString;
  6159. tmpString = MIDL_user_allocate(NM_WCSLEN(networkName));
  6160. if (tmpString == NULL) {
  6161. goto error_exit;
  6162. }
  6163. wcscpy(tmpString, networkName);
  6164. NetworkInfo->Name = tmpString;
  6165. tmpString = MIDL_user_allocate(NM_WCSLEN(Network->Description));
  6166. if (tmpString == NULL) {
  6167. goto error_exit;
  6168. }
  6169. wcscpy(tmpString, Network->Description);
  6170. NetworkInfo->Description = tmpString;
  6171. NetworkInfo->Role = Network->Role;
  6172. NetworkInfo->Priority = Network->Priority;
  6173. tmpString = MIDL_user_allocate(NM_WCSLEN(Network->Transport));
  6174. if (tmpString == NULL) {
  6175. goto error_exit;
  6176. }
  6177. wcscpy(tmpString, Network->Transport);
  6178. NetworkInfo->Transport = tmpString;
  6179. tmpString = MIDL_user_allocate(NM_WCSLEN(Network->Address));
  6180. if (tmpString == NULL) {
  6181. goto error_exit;
  6182. }
  6183. wcscpy(tmpString, Network->Address);
  6184. NetworkInfo->Address = tmpString;
  6185. tmpString = MIDL_user_allocate(NM_WCSLEN(Network->AddressMask));
  6186. if (tmpString == NULL) {
  6187. goto error_exit;
  6188. }
  6189. wcscpy(tmpString, Network->AddressMask);
  6190. NetworkInfo->AddressMask = tmpString;
  6191. return(ERROR_SUCCESS);
  6192. error_exit:
  6193. ClNetFreeNetworkInfo(NetworkInfo);
  6194. return(status);
  6195. } // NmpGetNetworkObjectInfo
  6196. VOID
  6197. NmpDeleteNetworkObject(
  6198. IN PNM_NETWORK Network,
  6199. IN BOOLEAN IssueEvent
  6200. )
  6201. /*++
  6202. Routine Description:
  6203. Deletes a cluster network object.
  6204. Arguments:
  6205. Network - A pointer to the network object to delete.
  6206. IssueEvent - TRUE if a NETWORK_DELETED event should be issued when this
  6207. object is created. FALSE otherwise.
  6208. Return Value:
  6209. None.
  6210. Notes:
  6211. Called with NM global lock held.
  6212. --*/
  6213. {
  6214. DWORD status;
  6215. PLIST_ENTRY entry;
  6216. LPWSTR networkId = (LPWSTR) OmObjectId(Network);
  6217. BOOLEAN wasInternalNetwork = FALSE;
  6218. if (NM_DELETE_PENDING(Network)) {
  6219. CL_ASSERT(!NM_OM_INSERTED(Network));
  6220. return;
  6221. }
  6222. ClRtlLogPrint(LOG_NOISE,
  6223. "[NM] Deleting object for network %1!ws!.\n",
  6224. networkId
  6225. );
  6226. CL_ASSERT(IsListEmpty(&(Network->InterfaceList)));
  6227. Network->Flags |= NM_FLAG_DELETE_PENDING;
  6228. //
  6229. // Remove from the object lists
  6230. //
  6231. if (NM_OM_INSERTED(Network)) {
  6232. status = OmRemoveObject(Network);
  6233. CL_ASSERT(status == ERROR_SUCCESS);
  6234. Network->Flags &= ~NM_FLAG_OM_INSERTED;
  6235. RemoveEntryList(&(Network->Linkage));
  6236. CL_ASSERT(NmpNetworkCount > 0);
  6237. NmpNetworkCount--;
  6238. if (NmpIsNetworkForInternalUse(Network)) {
  6239. RemoveEntryList(&(Network->InternalLinkage));
  6240. CL_ASSERT(NmpInternalNetworkCount > 0);
  6241. NmpInternalNetworkCount--;
  6242. wasInternalNetwork = TRUE;
  6243. }
  6244. if (NmpIsNetworkForClientAccess(Network)) {
  6245. CL_ASSERT(NmpClientNetworkCount > 0);
  6246. NmpClientNetworkCount--;
  6247. }
  6248. }
  6249. //
  6250. // Place the object on the deleted list
  6251. //
  6252. #if DBG
  6253. {
  6254. PLIST_ENTRY entry;
  6255. for ( entry = NmpDeletedNetworkList.Flink;
  6256. entry != &NmpDeletedNetworkList;
  6257. entry = entry->Flink
  6258. )
  6259. {
  6260. if (entry == &(Network->Linkage)) {
  6261. break;
  6262. }
  6263. }
  6264. CL_ASSERT(entry != &(Network->Linkage));
  6265. }
  6266. #endif DBG
  6267. InsertTailList(&NmpDeletedNetworkList, &(Network->Linkage));
  6268. if (NmpIsNetworkEnabledForUse(Network)) {
  6269. //
  6270. // Deregister the network from the cluster transport
  6271. //
  6272. NmpDeregisterNetwork(Network);
  6273. }
  6274. //
  6275. // Issue an event if needed
  6276. //
  6277. if (IssueEvent) {
  6278. ClRtlLogPrint(LOG_NOISE,
  6279. "[NM] Issuing network deleted event for network %1!ws!.\n",
  6280. networkId
  6281. );
  6282. ClusterEvent(CLUSTER_EVENT_NETWORK_DELETED, Network);
  6283. //
  6284. // Issue a cluster property change event if this network was
  6285. // used for internal communication. The network priority list
  6286. // was changed.
  6287. //
  6288. if (wasInternalNetwork) {
  6289. NmpIssueClusterPropertyChangeEvent();
  6290. }
  6291. }
  6292. //
  6293. // Remove the initial reference so the object can be destroyed.
  6294. //
  6295. OmDereferenceObject(Network);
  6296. return;
  6297. } // NmpDeleteNetworkObject
  6298. BOOL
  6299. NmpDestroyNetworkObject(
  6300. PNM_NETWORK Network
  6301. )
  6302. {
  6303. DWORD status;
  6304. ClRtlLogPrint(LOG_NOISE,
  6305. "[NM] destroying object for network %1!ws!\n",
  6306. OmObjectId(Network)
  6307. );
  6308. CL_ASSERT(NM_DELETE_PENDING(Network));
  6309. CL_ASSERT(!NM_OM_INSERTED(Network));
  6310. CL_ASSERT(Network->InterfaceCount == 0);
  6311. //
  6312. // Remove the network from the deleted list
  6313. //
  6314. #if DBG
  6315. {
  6316. PLIST_ENTRY entry;
  6317. for ( entry = NmpDeletedNetworkList.Flink;
  6318. entry != &NmpDeletedNetworkList;
  6319. entry = entry->Flink
  6320. )
  6321. {
  6322. if (entry == &(Network->Linkage)) {
  6323. break;
  6324. }
  6325. }
  6326. CL_ASSERT(entry == &(Network->Linkage));
  6327. }
  6328. #endif DBG
  6329. RemoveEntryList(&(Network->Linkage));
  6330. NM_FREE_OBJECT_FIELD(Network, Description);
  6331. NM_FREE_OBJECT_FIELD(Network, Transport);
  6332. NM_FREE_OBJECT_FIELD(Network, Address);
  6333. NM_FREE_OBJECT_FIELD(Network, AddressMask);
  6334. if (Network->ConnectivityVector != NULL) {
  6335. LocalFree(Network->ConnectivityVector);
  6336. Network->ConnectivityVector = NULL;
  6337. }
  6338. if (Network->StateWorkVector != NULL) {
  6339. LocalFree(Network->StateWorkVector);
  6340. Network->StateWorkVector = NULL;
  6341. }
  6342. if (Network->ConnectivityMatrix != NULL) {
  6343. LocalFree(Network->ConnectivityMatrix);
  6344. Network->ConnectivityMatrix = NULL;
  6345. }
  6346. NM_MIDL_FREE_OBJECT_FIELD(Network, MulticastAddress);
  6347. if (Network->EncryptedMulticastKey != NULL) {
  6348. LocalFree(Network->EncryptedMulticastKey);
  6349. Network->EncryptedMulticastKey = NULL;
  6350. }
  6351. NM_MIDL_FREE_OBJECT_FIELD(Network, MulticastLeaseServer);
  6352. NM_MIDL_FREE_OBJECT_FIELD(Network, MulticastLeaseRequestId.ClientUID);
  6353. NmpFreeMulticastAddressReleaseList(Network);
  6354. return(TRUE);
  6355. } // NmpDestroyNetworkObject
  6356. DWORD
  6357. NmpEnumNetworkObjects(
  6358. OUT PNM_NETWORK_ENUM * NetworkEnum
  6359. )
  6360. /*++
  6361. Routine Description:
  6362. Reads information about defined cluster networks from the cluster
  6363. objects and builds an enumeration structure to hold the information.
  6364. Arguments:
  6365. NetworkEnum - A pointer to the variable into which to place a pointer to
  6366. the allocated network enumeration.
  6367. Return Value:
  6368. ERROR_SUCCESS if the routine succeeds.
  6369. A Win32 error code otherwise.
  6370. Notes:
  6371. Called with the NmpLock held.
  6372. --*/
  6373. {
  6374. DWORD status = ERROR_SUCCESS;
  6375. PNM_NETWORK_ENUM networkEnum = NULL;
  6376. DWORD i;
  6377. DWORD valueLength;
  6378. PLIST_ENTRY entry;
  6379. PNM_NETWORK network;
  6380. *NetworkEnum = NULL;
  6381. if (NmpNetworkCount == 0) {
  6382. valueLength = sizeof(NM_NETWORK_ENUM);
  6383. }
  6384. else {
  6385. valueLength = sizeof(NM_NETWORK_ENUM) +
  6386. (sizeof(NM_NETWORK_INFO) * (NmpNetworkCount - 1));
  6387. }
  6388. networkEnum = MIDL_user_allocate(valueLength);
  6389. if (networkEnum == NULL) {
  6390. return(ERROR_NOT_ENOUGH_MEMORY);
  6391. }
  6392. ZeroMemory(networkEnum, valueLength);
  6393. for (entry = NmpNetworkList.Flink, i=0;
  6394. entry != &NmpNetworkList;
  6395. entry = entry->Flink, i++
  6396. )
  6397. {
  6398. network = CONTAINING_RECORD(entry, NM_NETWORK, Linkage);
  6399. status = NmpGetNetworkObjectInfo(
  6400. network,
  6401. &(networkEnum->NetworkList[i])
  6402. );
  6403. if (status != ERROR_SUCCESS) {
  6404. ClNetFreeNetworkEnum(networkEnum);
  6405. return(status);
  6406. }
  6407. }
  6408. networkEnum->NetworkCount = NmpNetworkCount;
  6409. *NetworkEnum = networkEnum;
  6410. networkEnum = NULL;
  6411. return(ERROR_SUCCESS);
  6412. } // NmpEnumNetworkObjects
  6413. DWORD
  6414. NmpEnumNetworkObjectStates(
  6415. OUT PNM_NETWORK_STATE_ENUM * NetworkStateEnum
  6416. )
  6417. /*++
  6418. Routine Description:
  6419. Reads state information for all defined cluster networks
  6420. and fills in an enumeration structure.
  6421. Arguments:
  6422. NetworkStateEnum - A pointer to the variable into which to place a
  6423. pointer to the allocated interface enumeration.
  6424. Return Value:
  6425. ERROR_SUCCESS if the routine succeeds.
  6426. A Win32 error code otherwise.
  6427. Notes:
  6428. Called with the NmpLock held.
  6429. --*/
  6430. {
  6431. DWORD status = ERROR_SUCCESS;
  6432. PNM_NETWORK_STATE_ENUM networkStateEnum = NULL;
  6433. PNM_NETWORK_STATE_INFO networkStateInfo;
  6434. DWORD i;
  6435. DWORD valueLength;
  6436. PLIST_ENTRY entry;
  6437. PNM_NETWORK network;
  6438. LPWSTR networkId;
  6439. *NetworkStateEnum = NULL;
  6440. if (NmpNetworkCount == 0) {
  6441. valueLength = sizeof(NM_NETWORK_STATE_ENUM);
  6442. }
  6443. else {
  6444. valueLength =
  6445. sizeof(NM_NETWORK_STATE_ENUM) +
  6446. (sizeof(NM_NETWORK_STATE_INFO) * (NmpNetworkCount - 1));
  6447. }
  6448. networkStateEnum = MIDL_user_allocate(valueLength);
  6449. if (networkStateEnum == NULL) {
  6450. return(ERROR_NOT_ENOUGH_MEMORY);
  6451. }
  6452. ZeroMemory(networkStateEnum, valueLength);
  6453. for (entry = NmpNetworkList.Flink, i=0;
  6454. entry != &NmpNetworkList;
  6455. entry = entry->Flink, i++
  6456. )
  6457. {
  6458. network = CONTAINING_RECORD(entry, NM_NETWORK, Linkage);
  6459. networkId = (LPWSTR) OmObjectId(network);
  6460. networkStateInfo = &(networkStateEnum->NetworkList[i]);
  6461. networkStateInfo->State = network->State;
  6462. networkStateInfo->Id = MIDL_user_allocate(NM_WCSLEN(networkId));
  6463. if (networkStateInfo->Id == NULL) {
  6464. NmpFreeNetworkStateEnum(networkStateEnum);
  6465. return(ERROR_NOT_ENOUGH_MEMORY);
  6466. }
  6467. lstrcpyW(networkStateInfo->Id, networkId);
  6468. }
  6469. networkStateEnum->NetworkCount = NmpNetworkCount;
  6470. *NetworkStateEnum = networkStateEnum;
  6471. return(ERROR_SUCCESS);
  6472. } // NmpEnumNetworkObjectStates
  6473. DWORD
  6474. NmpGetNetworkMulticastKey(
  6475. IN LPWSTR NetworkId,
  6476. OUT PNM_NETWORK_MULTICASTKEY * NetworkMulticastKey
  6477. )
  6478. /*++
  6479. Routine Description:
  6480. Reads network multicast key for networt NetworkId.
  6481. Arguments:
  6482. NetworkId - Id of the network whose multicast key should be read.
  6483. NetworkMulticastKey - A pointer to the variable into which to place
  6484. the network multicast key.
  6485. Return Value:
  6486. ERROR_SUCCESS if the routine succeeds.
  6487. A Win32 error code otherwise.
  6488. Notes:
  6489. Called with the NmpLock held.
  6490. --*/
  6491. {
  6492. PNM_NETWORK_MULTICASTKEY networkMulticastKey;
  6493. PLIST_ENTRY entry;
  6494. PNM_NETWORK network;
  6495. PVOID MulticastKey = NULL;
  6496. DWORD MulticastKeyLength;
  6497. DWORD status = ERROR_SUCCESS;
  6498. LPWSTR networkId;
  6499. PVOID EncryptionKey = NULL;
  6500. DWORD EncryptionKeyLength;
  6501. PBYTE Salt = NULL;
  6502. PBYTE EncryptedMulticastKey = NULL;
  6503. DWORD EncryptedMulticastKeyLength;
  6504. PBYTE MAC = NULL;
  6505. DWORD MACLength;
  6506. BOOL found = FALSE;
  6507. networkMulticastKey = MIDL_user_allocate(sizeof(NM_NETWORK_MULTICASTKEY));
  6508. if (networkMulticastKey == NULL)
  6509. {
  6510. ClRtlLogPrint(LOG_UNUSUAL,
  6511. "[NM] Failed to allocate %1!u! bytes to marshall "
  6512. "encrypted multicast key.\n",
  6513. sizeof(NM_NETWORK_MULTICASTKEY)
  6514. );
  6515. return(ERROR_NOT_ENOUGH_MEMORY);
  6516. }
  6517. ZeroMemory(networkMulticastKey, sizeof(NM_NETWORK_MULTICASTKEY));
  6518. for (entry = NmpNetworkList.Flink;
  6519. entry != &NmpNetworkList;
  6520. entry = entry->Flink
  6521. )
  6522. {
  6523. network = CONTAINING_RECORD(entry, NM_NETWORK, Linkage);
  6524. networkId = (LPWSTR) OmObjectId(network);
  6525. if (wcscmp(NetworkId, networkId) == 0)
  6526. {
  6527. found = TRUE;
  6528. if (network->EncryptedMulticastKey != NULL)
  6529. {
  6530. //
  6531. // Set MulticastKeyExpires
  6532. //
  6533. networkMulticastKey->MulticastKeyExpires =
  6534. network->MulticastKeyExpires;
  6535. //
  6536. // Set EncryptedMulticastKey
  6537. //
  6538. status = NmpUnprotectData(network->EncryptedMulticastKey,
  6539. network->EncryptedMulticastKeyLength,
  6540. &MulticastKey,
  6541. &MulticastKeyLength
  6542. );
  6543. if (status != ERROR_SUCCESS)
  6544. {
  6545. ClRtlLogPrint(LOG_UNUSUAL,
  6546. "[NM] Failed to decrypt multicast key "
  6547. "for network %1!ws!, status %2!u!.\n",
  6548. networkId,
  6549. status
  6550. );
  6551. goto error_exit;
  6552. }
  6553. status = NmpDeriveClusterKey(
  6554. networkId,
  6555. NM_WCSLEN(networkId),
  6556. &EncryptionKey,
  6557. &EncryptionKeyLength
  6558. );
  6559. if (status != ERROR_SUCCESS)
  6560. {
  6561. ClRtlLogPrint(LOG_UNUSUAL,
  6562. "[NM] Failed to derive cluster key for "
  6563. "network %1!ws!, status %2!u!.\n",
  6564. networkId, status
  6565. );
  6566. goto error_exit;
  6567. }
  6568. MACLength = NMP_MAC_DATA_LENGTH_EXPECTED;
  6569. status = NmpEncryptDataAndCreateMAC(
  6570. NmCryptServiceProvider,
  6571. NMP_ENCRYPT_ALGORITHM,
  6572. NMP_KEY_LENGTH,
  6573. MulticastKey, // Data
  6574. MulticastKeyLength, // Data length
  6575. EncryptionKey,
  6576. EncryptionKeyLength,
  6577. TRUE, // Create salt
  6578. &Salt,
  6579. NMP_SALT_BUFFER_LEN,
  6580. &EncryptedMulticastKey,
  6581. &EncryptedMulticastKeyLength,
  6582. &MAC,
  6583. &MACLength
  6584. );
  6585. if (status != ERROR_SUCCESS)
  6586. {
  6587. ClRtlLogPrint(LOG_UNUSUAL,
  6588. "[NM] Failed to "
  6589. "encrypt data or generate MAC for "
  6590. "network %1!ws!, status %2!u!.\n",
  6591. networkId,
  6592. status
  6593. );
  6594. goto error_exit;
  6595. }
  6596. networkMulticastKey->EncryptedMulticastKey =
  6597. MIDL_user_allocate(EncryptedMulticastKeyLength);
  6598. if (networkMulticastKey->EncryptedMulticastKey == NULL) {
  6599. ClRtlLogPrint(LOG_UNUSUAL,
  6600. "[NM] Failed to allocate %1!u! bytes "
  6601. "for encrypted multicast key.\n",
  6602. EncryptedMulticastKeyLength
  6603. );
  6604. status = ERROR_NOT_ENOUGH_MEMORY;
  6605. goto error_exit;
  6606. }
  6607. CopyMemory(networkMulticastKey->EncryptedMulticastKey,
  6608. EncryptedMulticastKey,
  6609. EncryptedMulticastKeyLength
  6610. );
  6611. networkMulticastKey->EncryptedMulticastKeyLength =
  6612. EncryptedMulticastKeyLength;
  6613. //
  6614. // Set Salt
  6615. //
  6616. networkMulticastKey->Salt =
  6617. MIDL_user_allocate(NMP_SALT_BUFFER_LEN);
  6618. if (networkMulticastKey->Salt == NULL) {
  6619. ClRtlLogPrint(LOG_UNUSUAL,
  6620. "[NM] Failed to allocate %1!u! bytes "
  6621. "for encrypted multicast key salt.\n",
  6622. NMP_SALT_BUFFER_LEN
  6623. );
  6624. status = ERROR_NOT_ENOUGH_MEMORY;
  6625. goto error_exit;
  6626. }
  6627. CopyMemory(networkMulticastKey->Salt,
  6628. Salt,
  6629. NMP_SALT_BUFFER_LEN
  6630. );
  6631. networkMulticastKey->SaltLength =
  6632. NMP_SALT_BUFFER_LEN;
  6633. //
  6634. // Set MAC
  6635. //
  6636. networkMulticastKey->MAC =
  6637. MIDL_user_allocate(MACLength);
  6638. if (networkMulticastKey->MAC == NULL) {
  6639. ClRtlLogPrint(LOG_UNUSUAL,
  6640. "[NM] Failed to allocate %1!u! bytes "
  6641. "for encrypted multicast key MAC.\n",
  6642. MACLength
  6643. );
  6644. status = ERROR_NOT_ENOUGH_MEMORY;
  6645. goto error_exit;
  6646. }
  6647. CopyMemory(networkMulticastKey->MAC,
  6648. MAC,
  6649. MACLength
  6650. );
  6651. networkMulticastKey->MACLength =
  6652. MACLength;
  6653. //
  6654. // release MulticastKey
  6655. //
  6656. if (MulticastKey != NULL)
  6657. {
  6658. RtlSecureZeroMemory(MulticastKey, MulticastKeyLength);
  6659. LocalFree(MulticastKey);
  6660. MulticastKey = NULL;
  6661. }
  6662. //
  6663. // release EncryptionKey
  6664. //
  6665. if (EncryptionKey != NULL)
  6666. {
  6667. RtlSecureZeroMemory(EncryptionKey, EncryptionKeyLength);
  6668. LocalFree(EncryptionKey);
  6669. EncryptionKey = NULL;
  6670. }
  6671. } // if (network->EncryptedMulticastKey != NULL)
  6672. else {
  6673. ClRtlLogPrint(LOG_UNUSUAL,
  6674. "[NM] Network %1!ws! has no multicast key.\n",
  6675. networkId
  6676. );
  6677. }
  6678. break;
  6679. } // if (wcscmp(NetworkId, networkId) == 0)
  6680. } // for
  6681. if (found == FALSE)
  6682. {
  6683. ClRtlLogPrint(LOG_UNUSUAL,
  6684. "[NM] Unable to find network %1!ws!.\n",
  6685. networkId
  6686. );
  6687. status = ERROR_CLUSTER_NETWORK_NOT_FOUND;
  6688. goto error_exit;
  6689. }
  6690. *NetworkMulticastKey = networkMulticastKey;
  6691. error_exit:
  6692. if (MulticastKey != NULL)
  6693. {
  6694. RtlSecureZeroMemory(MulticastKey, MulticastKeyLength);
  6695. LocalFree(MulticastKey);
  6696. MulticastKey = NULL;
  6697. }
  6698. if (EncryptionKey != NULL)
  6699. {
  6700. RtlSecureZeroMemory(EncryptionKey, EncryptionKeyLength);
  6701. LocalFree(EncryptionKey);
  6702. EncryptionKey = NULL;
  6703. }
  6704. if (EncryptedMulticastKey != NULL)
  6705. {
  6706. HeapFree(GetProcessHeap(), 0, EncryptedMulticastKey);
  6707. }
  6708. if (Salt != NULL)
  6709. {
  6710. HeapFree(GetProcessHeap(), 0, Salt);
  6711. }
  6712. if (MAC != NULL)
  6713. {
  6714. HeapFree(GetProcessHeap(), 0, MAC);
  6715. }
  6716. if (status != ERROR_SUCCESS)
  6717. {
  6718. NmpFreeNetworkMulticastKey(networkMulticastKey
  6719. );
  6720. }
  6721. return (status);
  6722. } // NmpGetNetworkMulticastKey
  6723. /////////////////////////////////////////////////////////////////////////////
  6724. //
  6725. // Miscellaneous routines
  6726. //
  6727. /////////////////////////////////////////////////////////////////////////////
  6728. DWORD
  6729. NmpRegisterNetwork(
  6730. IN PNM_NETWORK Network,
  6731. IN BOOLEAN RetryOnFailure
  6732. )
  6733. /*++
  6734. Routine Description:
  6735. Registers a network and the associated interfaces with the
  6736. cluster transport and brings the network online.
  6737. Arguments:
  6738. Network - A pointer to the network to register.
  6739. Return Value:
  6740. ERROR_SUCCESS if successful.
  6741. A Win32 error code otherwise.
  6742. Notes:
  6743. Called with the NmpLock held.
  6744. --*/
  6745. {
  6746. PLIST_ENTRY entry;
  6747. PNM_INTERFACE netInterface;
  6748. DWORD status = ERROR_SUCCESS;
  6749. DWORD tempStatus;
  6750. PVOID tdiAddress = NULL;
  6751. ULONG tdiAddressLength = 0;
  6752. LPWSTR networkId = (LPWSTR) OmObjectId(Network);
  6753. PVOID tdiAddressInfo = NULL;
  6754. ULONG tdiAddressInfoLength = 0;
  6755. DWORD responseLength;
  6756. PNM_INTERFACE localInterface = Network->LocalInterface;
  6757. BOOLEAN restricted = FALSE;
  6758. BOOLEAN registered = FALSE;
  6759. if (Network->LocalInterface != NULL) {
  6760. if (!NmpIsNetworkRegistered(Network)) {
  6761. //
  6762. // Register the network
  6763. //
  6764. ClRtlLogPrint(LOG_NOISE,
  6765. "[NM] Registering network %1!ws! (%2!ws!) with cluster "
  6766. "transport.\n",
  6767. networkId,
  6768. OmObjectName(Network)
  6769. );
  6770. if (!NmpIsNetworkForInternalUse(Network)) {
  6771. restricted = TRUE;
  6772. }
  6773. status = ClusnetRegisterNetwork(
  6774. NmClusnetHandle,
  6775. Network->ShortId,
  6776. Network->Priority,
  6777. restricted
  6778. );
  6779. if (status == ERROR_SUCCESS) {
  6780. registered = TRUE;
  6781. //
  6782. // Bring the network online.
  6783. //
  6784. ClRtlLogPrint(LOG_NOISE,
  6785. "[NM] Bringing network %1!ws! online.\n",
  6786. networkId
  6787. );
  6788. status = ClRtlBuildTcpipTdiAddress(
  6789. localInterface->Address,
  6790. localInterface->ClusnetEndpoint,
  6791. &tdiAddress,
  6792. &tdiAddressLength
  6793. );
  6794. if (status == ERROR_SUCCESS) {
  6795. ClRtlQueryTcpipInformation(
  6796. NULL,
  6797. NULL,
  6798. &tdiAddressInfoLength
  6799. );
  6800. tdiAddressInfo = LocalAlloc(
  6801. LMEM_FIXED,
  6802. tdiAddressInfoLength
  6803. );
  6804. if (tdiAddressInfo != NULL) {
  6805. responseLength = tdiAddressInfoLength;
  6806. status = ClusnetOnlineNetwork(
  6807. NmClusnetHandle,
  6808. Network->ShortId,
  6809. L"\\Device\\Udp",
  6810. tdiAddress,
  6811. tdiAddressLength,
  6812. localInterface->AdapterId,
  6813. tdiAddressInfo,
  6814. &responseLength
  6815. );
  6816. if (status != ERROR_SUCCESS) {
  6817. ClRtlLogPrint(LOG_CRITICAL,
  6818. "[NM] Cluster transport failed to bring "
  6819. "network %1!ws! online, status %2!u!.\n",
  6820. networkId,
  6821. status
  6822. );
  6823. }
  6824. else {
  6825. CL_ASSERT(responseLength == tdiAddressInfoLength);
  6826. }
  6827. LocalFree(tdiAddressInfo);
  6828. }
  6829. else {
  6830. status = ERROR_NOT_ENOUGH_MEMORY;
  6831. ClRtlLogPrint(LOG_UNUSUAL,
  6832. "[NM] Failed to allocate memory to register "
  6833. "network %1!ws! with cluster transport.\n",
  6834. networkId
  6835. );
  6836. }
  6837. LocalFree(tdiAddress);
  6838. }
  6839. else {
  6840. ClRtlLogPrint(LOG_CRITICAL,
  6841. "[NM] Failed to build address to register "
  6842. "network %1!ws! withh cluster transport, "
  6843. "status %2!u!.\n",
  6844. networkId,
  6845. status
  6846. );
  6847. }
  6848. }
  6849. else {
  6850. ClRtlLogPrint(LOG_CRITICAL,
  6851. "[NM] Failed to register network %1!ws! with cluster "
  6852. "transport, status %2!u!.\n",
  6853. networkId,
  6854. status
  6855. );
  6856. }
  6857. if (status == ERROR_SUCCESS) {
  6858. Network->Flags |= NM_FLAG_NET_REGISTERED;
  6859. Network->RegistrationRetryTimeout = 0;
  6860. //
  6861. // Start multicast.
  6862. //
  6863. NmpStartMulticast(Network, NmStartMulticastDynamic);
  6864. }
  6865. else {
  6866. WCHAR string[16];
  6867. wsprintfW(&(string[0]), L"%u", status);
  6868. CsLogEvent2(
  6869. LOG_UNUSUAL,
  6870. NM_EVENT_REGISTER_NETWORK_FAILED,
  6871. OmObjectName(Network),
  6872. string
  6873. );
  6874. if (registered) {
  6875. NmpDeregisterNetwork(Network);
  6876. }
  6877. //
  6878. // Retry if the error is transient.
  6879. //
  6880. if ( RetryOnFailure &&
  6881. ( (status == ERROR_INVALID_NETNAME) ||
  6882. (status == ERROR_NOT_ENOUGH_MEMORY) ||
  6883. (status == ERROR_NO_SYSTEM_RESOURCES)
  6884. )
  6885. )
  6886. {
  6887. NmpStartNetworkRegistrationRetryTimer(Network);
  6888. status = ERROR_SUCCESS;
  6889. }
  6890. return(status);
  6891. }
  6892. }
  6893. //
  6894. // Register the network's interfaces.
  6895. //
  6896. for (entry = Network->InterfaceList.Flink;
  6897. entry != &(Network->InterfaceList);
  6898. entry = entry->Flink
  6899. )
  6900. {
  6901. netInterface = CONTAINING_RECORD(
  6902. entry,
  6903. NM_INTERFACE,
  6904. NetworkLinkage
  6905. );
  6906. if (!NmpIsInterfaceRegistered(netInterface)) {
  6907. tempStatus = NmpRegisterInterface(
  6908. netInterface,
  6909. RetryOnFailure
  6910. );
  6911. if (tempStatus != ERROR_SUCCESS) {
  6912. status = tempStatus;
  6913. }
  6914. }
  6915. }
  6916. }
  6917. return(status);
  6918. } // NmpRegisterNetwork
  6919. VOID
  6920. NmpDeregisterNetwork(
  6921. IN PNM_NETWORK Network
  6922. )
  6923. /*++
  6924. Routine Description:
  6925. Deregisters a network and the associated interfaces from the
  6926. cluster transport.
  6927. Arguments:
  6928. Network - A pointer to the network to deregister.
  6929. Return Value:
  6930. None.
  6931. Notes:
  6932. Called with the NmpLock held.
  6933. --*/
  6934. {
  6935. DWORD status;
  6936. PNM_INTERFACE netInterface;
  6937. PLIST_ENTRY entry;
  6938. ClRtlLogPrint(LOG_NOISE,
  6939. "[NM] Deregistering network %1!ws! (%2!ws!) from cluster transport.\n",
  6940. OmObjectId(Network),
  6941. OmObjectName(Network)
  6942. );
  6943. status = ClusnetDeregisterNetwork(
  6944. NmClusnetHandle,
  6945. Network->ShortId
  6946. );
  6947. CL_ASSERT(
  6948. (status == ERROR_SUCCESS) ||
  6949. (status == ERROR_CLUSTER_NETWORK_NOT_FOUND)
  6950. );
  6951. //
  6952. // Mark all of the network's interfaces as deregistered.
  6953. //
  6954. for (entry = Network->InterfaceList.Flink;
  6955. entry != &(Network->InterfaceList);
  6956. entry = entry->Flink
  6957. )
  6958. {
  6959. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, NetworkLinkage);
  6960. netInterface->Flags &= ~NM_FLAG_IF_REGISTERED;
  6961. }
  6962. //
  6963. // Mark the network as deregistered
  6964. //
  6965. Network->Flags &= ~NM_FLAG_NET_REGISTERED;
  6966. return;
  6967. } // NmpDeregisterNetwork
  6968. VOID
  6969. NmpInsertInternalNetwork(
  6970. PNM_NETWORK Network
  6971. )
  6972. /*++
  6973. Routine Description:
  6974. Inserts a network into internal networks list based on its priority.
  6975. Arguments:
  6976. Network - A pointer to the network object to be inserted.
  6977. Return Value:
  6978. None.
  6979. Notes:
  6980. Called with the NmpLock held.
  6981. --*/
  6982. {
  6983. PLIST_ENTRY entry;
  6984. PNM_NETWORK network;
  6985. //
  6986. // Maintain internal networks in highest to lowest
  6987. // (numerically lowest to highest) priority order.
  6988. //
  6989. for (entry = NmpInternalNetworkList.Flink;
  6990. entry != &NmpInternalNetworkList;
  6991. entry = entry->Flink
  6992. )
  6993. {
  6994. network = CONTAINING_RECORD(entry, NM_NETWORK, InternalLinkage);
  6995. if (Network->Priority < network->Priority) {
  6996. break;
  6997. }
  6998. }
  6999. //
  7000. // Insert the network in front of this entry.
  7001. //
  7002. InsertTailList(entry, &(Network->InternalLinkage));
  7003. return;
  7004. } // NmpInsertNetwork
  7005. DWORD
  7006. NmpValidateNetworkRoleChange(
  7007. PNM_NETWORK Network,
  7008. CLUSTER_NETWORK_ROLE NewRole
  7009. )
  7010. {
  7011. if ( !(NewRole & ClusterNetworkRoleInternalUse) &&
  7012. NmpIsNetworkForInternalUse(Network)
  7013. )
  7014. {
  7015. //
  7016. // This change eliminates an internal network. This is only
  7017. // legal if we would still have at least one internal network
  7018. // between all active nodes.
  7019. //
  7020. if ((NmpInternalNetworkCount < 2) || !NmpVerifyConnectivity(Network)) {
  7021. return(ERROR_CLUSTER_LAST_INTERNAL_NETWORK);
  7022. }
  7023. }
  7024. if ( ( !(NewRole & ClusterNetworkRoleClientAccess) )
  7025. &&
  7026. NmpIsNetworkForClientAccess(Network)
  7027. )
  7028. {
  7029. BOOL hasDependents;
  7030. //
  7031. // This change eliminates a public network. This is only
  7032. // legal if there are no dependencies (IP address resources) on
  7033. // the network.
  7034. //
  7035. NmpReleaseLock();
  7036. hasDependents = FmCheckNetworkDependency(OmObjectId(Network));
  7037. NmpAcquireLock();
  7038. if (hasDependents) {
  7039. return(ERROR_CLUSTER_NETWORK_HAS_DEPENDENTS);
  7040. }
  7041. }
  7042. return(ERROR_SUCCESS);
  7043. } // NmpValidateNetworkRoleChange
  7044. BOOLEAN
  7045. NmpVerifyNodeConnectivity(
  7046. PNM_NODE Node1,
  7047. PNM_NODE Node2,
  7048. PNM_NETWORK ExcludedNetwork
  7049. )
  7050. {
  7051. PLIST_ENTRY ifEntry1, ifEntry2;
  7052. PNM_NETWORK network;
  7053. PNM_INTERFACE interface1, interface2;
  7054. for (ifEntry1 = Node1->InterfaceList.Flink;
  7055. ifEntry1 != &(Node1->InterfaceList);
  7056. ifEntry1 = ifEntry1->Flink
  7057. )
  7058. {
  7059. interface1 = CONTAINING_RECORD(
  7060. ifEntry1,
  7061. NM_INTERFACE,
  7062. NodeLinkage
  7063. );
  7064. network = interface1->Network;
  7065. if ( (network != ExcludedNetwork) &&
  7066. NmpIsNetworkForInternalUse(network)
  7067. )
  7068. {
  7069. for (ifEntry2 = Node2->InterfaceList.Flink;
  7070. ifEntry2 != &(Node2->InterfaceList);
  7071. ifEntry2 = ifEntry2->Flink
  7072. )
  7073. {
  7074. interface2 = CONTAINING_RECORD(
  7075. ifEntry2,
  7076. NM_INTERFACE,
  7077. NodeLinkage
  7078. );
  7079. if (interface2->Network == interface1->Network) {
  7080. ClRtlLogPrint(LOG_NOISE,
  7081. "[NM] nodes %1!u! & %2!u! are connected over "
  7082. "network %3!ws!\n",
  7083. Node1->NodeId,
  7084. Node2->NodeId,
  7085. OmObjectId(interface1->Network)
  7086. );
  7087. return(TRUE);
  7088. }
  7089. }
  7090. }
  7091. }
  7092. ClRtlLogPrint(LOG_NOISE,
  7093. "[NM] Nodes %1!u! & %2!u! are not connected over any internal "
  7094. "networks\n",
  7095. Node1->NodeId,
  7096. Node2->NodeId
  7097. );
  7098. return(FALSE);
  7099. } // NmpVerifyNodeConnectivity
  7100. BOOLEAN
  7101. NmpVerifyConnectivity(
  7102. PNM_NETWORK ExcludedNetwork
  7103. )
  7104. {
  7105. PLIST_ENTRY node1Entry, node2Entry;
  7106. PNM_NODE node1, node2;
  7107. ClRtlLogPrint(LOG_NOISE, "[NM] Verifying connectivity\n");
  7108. for (node1Entry = NmpNodeList.Flink;
  7109. node1Entry != &NmpNodeList;
  7110. node1Entry = node1Entry->Flink
  7111. )
  7112. {
  7113. node1 = CONTAINING_RECORD(
  7114. node1Entry,
  7115. NM_NODE,
  7116. Linkage
  7117. );
  7118. if (NM_NODE_UP(node1)) {
  7119. for (node2Entry = node1->Linkage.Flink;
  7120. node2Entry != &NmpNodeList;
  7121. node2Entry = node2Entry->Flink
  7122. )
  7123. {
  7124. node2 = CONTAINING_RECORD(
  7125. node2Entry,
  7126. NM_NODE,
  7127. Linkage
  7128. );
  7129. if (NM_NODE_UP(node2)) {
  7130. ClRtlLogPrint(LOG_NOISE,
  7131. "[NM] Verifying nodes %1!u! & %2!u! are connected\n",
  7132. node1->NodeId,
  7133. node2->NodeId
  7134. );
  7135. if (!NmpVerifyNodeConnectivity(
  7136. node1,
  7137. node2,
  7138. ExcludedNetwork
  7139. )
  7140. )
  7141. {
  7142. return(FALSE);
  7143. }
  7144. }
  7145. }
  7146. }
  7147. }
  7148. return(TRUE);
  7149. } // NmpVerifyConnectivity
  7150. VOID
  7151. NmpIssueClusterPropertyChangeEvent(
  7152. VOID
  7153. )
  7154. {
  7155. DWORD status;
  7156. DWORD valueLength = 0;
  7157. DWORD valueSize = 0;
  7158. PWCHAR clusterName = NULL;
  7159. //
  7160. // The notification API expects a
  7161. // cluster name to be associated with this event.
  7162. //
  7163. status = NmpQueryString(
  7164. DmClusterParametersKey,
  7165. CLUSREG_NAME_CLUS_NAME,
  7166. REG_SZ,
  7167. &clusterName,
  7168. &valueLength,
  7169. &valueSize
  7170. );
  7171. if (status == ERROR_SUCCESS) {
  7172. ClusterEventEx(
  7173. CLUSTER_EVENT_PROPERTY_CHANGE,
  7174. EP_CONTEXT_VALID | EP_FREE_CONTEXT,
  7175. clusterName
  7176. );
  7177. //
  7178. // clusterName will be freed by the event processing code.
  7179. //
  7180. }
  7181. else {
  7182. ClRtlLogPrint(LOG_WARNING,
  7183. "[NM] Failed to issue cluster property change event, "
  7184. "status %1!u!.\n",
  7185. status
  7186. );
  7187. }
  7188. return;
  7189. } // NmpIssueClusterPropertyChangeEvent
  7190. DWORD
  7191. NmpMarshallObjectInfo(
  7192. IN const PRESUTIL_PROPERTY_ITEM PropertyTable,
  7193. IN PVOID ObjectInfo,
  7194. OUT PVOID * PropertyList,
  7195. OUT LPDWORD PropertyListSize
  7196. )
  7197. {
  7198. DWORD status;
  7199. PVOID propertyList = NULL;
  7200. DWORD propertyListSize = 0;
  7201. DWORD bytesReturned = 0;
  7202. DWORD bytesRequired = 0;
  7203. status = ClRtlPropertyListFromParameterBlock(
  7204. PropertyTable,
  7205. NULL,
  7206. &propertyListSize,
  7207. (LPBYTE) ObjectInfo,
  7208. &bytesReturned,
  7209. &bytesRequired
  7210. );
  7211. if (status != ERROR_MORE_DATA) {
  7212. CL_ASSERT(status != ERROR_SUCCESS);
  7213. return(status);
  7214. }
  7215. CL_ASSERT(bytesRequired > 0);
  7216. propertyList = MIDL_user_allocate(bytesRequired);
  7217. if (propertyList == NULL) {
  7218. return(ERROR_NOT_ENOUGH_MEMORY);
  7219. }
  7220. propertyListSize = bytesRequired;
  7221. status = ClRtlPropertyListFromParameterBlock(
  7222. PropertyTable,
  7223. propertyList,
  7224. &propertyListSize,
  7225. (LPBYTE) ObjectInfo,
  7226. &bytesReturned,
  7227. &bytesRequired
  7228. );
  7229. if (status != ERROR_SUCCESS) {
  7230. CL_ASSERT(status != ERROR_MORE_DATA);
  7231. MIDL_user_free(propertyList);
  7232. }
  7233. else {
  7234. CL_ASSERT(bytesReturned == propertyListSize);
  7235. *PropertyList = propertyList;
  7236. *PropertyListSize = bytesReturned;
  7237. }
  7238. return(status);
  7239. } // NmpMarshallObjectInfo
  7240. VOID
  7241. NmpReferenceNetwork(
  7242. PNM_NETWORK Network
  7243. )
  7244. {
  7245. OmReferenceObject(Network);
  7246. return;
  7247. }
  7248. VOID
  7249. NmpDereferenceNetwork(
  7250. PNM_NETWORK Network
  7251. )
  7252. {
  7253. OmDereferenceObject(Network);
  7254. return;
  7255. }
  7256. PNM_NETWORK
  7257. NmpReferenceNetworkByAddress(
  7258. LPWSTR NetworkAddress,
  7259. LPWSTR NetworkMask
  7260. )
  7261. /*++
  7262. Notes:
  7263. Called with NM lock held.
  7264. --*/
  7265. {
  7266. PNM_NETWORK network;
  7267. PLIST_ENTRY entry;
  7268. for ( entry = NmpNetworkList.Flink;
  7269. entry != &NmpNetworkList;
  7270. entry = entry->Flink
  7271. )
  7272. {
  7273. network = CONTAINING_RECORD(entry, NM_NETWORK, Linkage);
  7274. if ((lstrcmpW(network->Address, NetworkAddress) == 0) &&
  7275. (lstrcmpW(network->AddressMask, NetworkMask) == 0)) {
  7276. NmpReferenceNetwork(network);
  7277. return(network);
  7278. }
  7279. }
  7280. return(NULL);
  7281. } // NmpReferenceNetworkByAddress
  7282. PNM_NETWORK
  7283. NmpReferenceNetworkByRemoteAddress(
  7284. LPWSTR RemoteAddress
  7285. )
  7286. /*++
  7287. Routine Description:
  7288. Search for the network object whose address and subnet mask
  7289. match RemoteAddress. Reference and return that network object.
  7290. Arguments:
  7291. RemoteAddress - remote network address
  7292. Return value:
  7293. Reference network object, or NULL if no match found
  7294. Notes:
  7295. Called with NM lock held.
  7296. --*/
  7297. {
  7298. ULONG remoteAddress;
  7299. PNM_NETWORK network;
  7300. PLIST_ENTRY entry;
  7301. DWORD error;
  7302. error = ClRtlTcpipStringToAddress(RemoteAddress, &remoteAddress);
  7303. if (error != ERROR_SUCCESS) {
  7304. ClRtlLogPrint(LOG_UNUSUAL,
  7305. "[NM] Failed to parse remote address %1!ws!, error %2!u!.\n",
  7306. RemoteAddress, error
  7307. );
  7308. return(NULL);
  7309. }
  7310. for ( entry = NmpNetworkList.Flink;
  7311. entry != &NmpNetworkList;
  7312. entry = entry->Flink
  7313. )
  7314. {
  7315. ULONG networkAddress;
  7316. ULONG networkMask;
  7317. network = CONTAINING_RECORD(entry, NM_NETWORK, Linkage);
  7318. if (network->Address == NULL || network->AddressMask == NULL) {
  7319. continue;
  7320. }
  7321. error = ClRtlTcpipStringToAddress(network->Address, &networkAddress);
  7322. if (error != ERROR_SUCCESS) {
  7323. ClRtlLogPrint(LOG_UNUSUAL,
  7324. "[NM] Failed to parse network address %1!ws!, error %2!u!.\n",
  7325. network->Address, error
  7326. );
  7327. continue;
  7328. }
  7329. error = ClRtlTcpipStringToAddress(network->AddressMask, &networkMask);
  7330. if (error != ERROR_SUCCESS) {
  7331. ClRtlLogPrint(LOG_UNUSUAL,
  7332. "[NM] Failed to parse network address mask %1!ws!, error %2!u!.\n",
  7333. network->AddressMask, error
  7334. );
  7335. continue;
  7336. }
  7337. if (ClRtlAreTcpipAddressesOnSameSubnet(
  7338. remoteAddress,
  7339. networkAddress,
  7340. networkMask
  7341. )) {
  7342. NmpReferenceNetwork(network);
  7343. return(network);
  7344. }
  7345. }
  7346. return(NULL);
  7347. } // NmpReferenceNetworkByRemoteAddress
  7348. BOOLEAN
  7349. NmpCheckForNetwork(
  7350. VOID
  7351. )
  7352. /*++
  7353. Routine Description:
  7354. Checks whether at least one network on this node configured for MSCS
  7355. has media sense.
  7356. Arguments:
  7357. None.
  7358. Return Value:
  7359. TRUE if a viable network is found. FALSE otherwise.
  7360. Notes:
  7361. Called with and returns with no locks held.
  7362. --*/
  7363. {
  7364. PLIST_ENTRY entry;
  7365. PNM_NETWORK network;
  7366. BOOLEAN haveNetwork = FALSE;
  7367. DWORD lockRetries = 3;
  7368. BOOL lockAcquired = FALSE;
  7369. //
  7370. // In order to examine our network interfaces, we need to
  7371. // acquire the NM lock, but if the NM lock is tied up for
  7372. // a long time (e.g. a local transaction with a lost MNS
  7373. // share), then we don't want to block arbitration forever.
  7374. // Try to obtain the lock four times, sleeping 150 msecs before
  7375. // retries, for a total of approximately one half second.
  7376. //
  7377. lockAcquired = TryEnterCriticalSection(&NmpLock);
  7378. while (!lockAcquired && lockRetries-- > 0) {
  7379. Sleep(150);
  7380. lockAcquired = TryEnterCriticalSection(&NmpLock);
  7381. }
  7382. if (!lockAcquired) {
  7383. ClRtlLogPrint(LOG_UNUSUAL,
  7384. "[NM] Failed to acquire NM lock while checking "
  7385. "networks prior to arbitration. Assuming we have "
  7386. "network connectivity to avoid further arbitration "
  7387. "delay.\n"
  7388. );
  7389. return(TRUE);
  7390. }
  7391. for (entry = NmpNetworkList.Flink;
  7392. entry != &NmpNetworkList;
  7393. entry = entry->Flink
  7394. )
  7395. {
  7396. network = CONTAINING_RECORD(
  7397. entry,
  7398. NM_NETWORK,
  7399. Linkage
  7400. );
  7401. // if a network's local interface is disabled, it is not
  7402. // considered a viable network. in this case the
  7403. // LocalInterface field is NULL.
  7404. if (network->LocalInterface != NULL) {
  7405. if (NmpVerifyLocalInterfaceConnected(network->LocalInterface)) {
  7406. haveNetwork = TRUE;
  7407. break;
  7408. } else {
  7409. ClRtlLogPrint(LOG_UNUSUAL,
  7410. "[NM] Network adapter %1!ws! with address %2!ws! "
  7411. "reported not connected.\n",
  7412. network->LocalInterface->AdapterId,
  7413. network->LocalInterface->Address
  7414. );
  7415. }
  7416. }
  7417. }
  7418. NmpReleaseLock();
  7419. if (!haveNetwork) {
  7420. SetLastError(ERROR_NETWORK_NOT_AVAILABLE);
  7421. }
  7422. return(haveNetwork);
  7423. } // NmpCheckForNetwork