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.

7467 lines
205 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. interface.c
  5. Abstract:
  6. Implements the Node Manager network interface management routines.
  7. Author:
  8. Mike Massa (mikemas) 7-Nov-1996
  9. Revision History:
  10. --*/
  11. #include "nmp.h"
  12. #include <iphlpapi.h>
  13. #include <iprtrmib.h>
  14. #include <ntddndis.h>
  15. #include <ndispnp.h>
  16. /////////////////////////////////////////////////////////////////////////////
  17. //
  18. // Data
  19. //
  20. /////////////////////////////////////////////////////////////////////////////
  21. #define NM_MAX_IF_PING_ENUM_SIZE 10
  22. #define NM_MAX_UNION_PING_ENUM_SIZE 5
  23. LIST_ENTRY NmpInterfaceList = {NULL, NULL};
  24. LIST_ENTRY NmpDeletedInterfaceList = {NULL, NULL};
  25. DWORD NmpInterfaceCount = 0;
  26. WCHAR NmpUnknownString[] = L"<Unknown>";
  27. WCHAR NmpNullString[] = L"";
  28. RESUTIL_PROPERTY_ITEM
  29. NmpInterfaceProperties[] =
  30. {
  31. {
  32. L"Id", NULL, CLUSPROP_FORMAT_SZ,
  33. 0, 0, 0,
  34. 0,
  35. FIELD_OFFSET(NM_INTERFACE_INFO2, Id)
  36. },
  37. {
  38. CLUSREG_NAME_NETIFACE_NAME, NULL, CLUSPROP_FORMAT_SZ,
  39. 0, 0, 0,
  40. 0,
  41. FIELD_OFFSET(NM_INTERFACE_INFO2, Name)
  42. },
  43. {
  44. CLUSREG_NAME_NETIFACE_DESC, NULL, CLUSPROP_FORMAT_SZ,
  45. (DWORD_PTR) NmpNullString, 0, 0,
  46. 0,
  47. FIELD_OFFSET(NM_INTERFACE_INFO2, Description)
  48. },
  49. {
  50. CLUSREG_NAME_NETIFACE_NODE, NULL, CLUSPROP_FORMAT_SZ,
  51. 0, 0, 0,
  52. 0,
  53. FIELD_OFFSET(NM_INTERFACE_INFO2, NodeId)
  54. },
  55. {
  56. CLUSREG_NAME_NETIFACE_NETWORK, NULL, CLUSPROP_FORMAT_SZ,
  57. 0, 0, 0,
  58. 0,
  59. FIELD_OFFSET(NM_INTERFACE_INFO2, NetworkId)
  60. },
  61. {
  62. CLUSREG_NAME_NETIFACE_ADAPTER_NAME, NULL, CLUSPROP_FORMAT_SZ,
  63. 0, 0, 0,
  64. 0,
  65. FIELD_OFFSET(NM_INTERFACE_INFO2, AdapterName)
  66. },
  67. {
  68. CLUSREG_NAME_NET_ADDRESS, NULL, CLUSPROP_FORMAT_SZ,
  69. 0, 0, 0,
  70. 0,
  71. FIELD_OFFSET(NM_INTERFACE_INFO2, Address)
  72. },
  73. {
  74. CLUSREG_NAME_NETIFACE_ENDPOINT, NULL, CLUSPROP_FORMAT_SZ,
  75. 0, 0, 0,
  76. 0,
  77. FIELD_OFFSET(NM_INTERFACE_INFO2, ClusnetEndpoint)
  78. },
  79. {
  80. CLUSREG_NAME_NETIFACE_STATE, NULL, CLUSPROP_FORMAT_DWORD,
  81. 0, 0, 0xFFFFFFFF,
  82. 0,
  83. FIELD_OFFSET(NM_INTERFACE_INFO2, State)
  84. },
  85. {
  86. CLUSREG_NAME_NETIFACE_ADAPTER_ID, NULL, CLUSPROP_FORMAT_SZ,
  87. 0, 0, 0,
  88. 0,
  89. FIELD_OFFSET(NM_INTERFACE_INFO2, AdapterId)
  90. },
  91. {
  92. 0
  93. }
  94. };
  95. /////////////////////////////////////////////////////////////////////////////
  96. //
  97. // Initialization & cleanup routines
  98. //
  99. /////////////////////////////////////////////////////////////////////////////
  100. DWORD
  101. NmpInitializeInterfaces(
  102. VOID
  103. )
  104. /*++
  105. Routine Description:
  106. Initializes network interface resources.
  107. Arguments:
  108. None.
  109. Return Value:
  110. A Win32 status value.
  111. --*/
  112. {
  113. DWORD status;
  114. OM_OBJECT_TYPE_INITIALIZE objectTypeInitializer;
  115. ClRtlLogPrint(LOG_NOISE,"[NM] Initializing network interfaces.\n");
  116. //
  117. // Create the network interface object type
  118. //
  119. ZeroMemory(&objectTypeInitializer, sizeof(OM_OBJECT_TYPE_INITIALIZE));
  120. objectTypeInitializer.ObjectSize = sizeof(NM_INTERFACE);
  121. objectTypeInitializer.Signature = NM_INTERFACE_SIG;
  122. objectTypeInitializer.Name = L"Network Interface";
  123. objectTypeInitializer.DeleteObjectMethod = &NmpDestroyInterfaceObject;
  124. status = OmCreateType(ObjectTypeNetInterface, &objectTypeInitializer);
  125. if (status != ERROR_SUCCESS) {
  126. WCHAR errorString[12];
  127. wsprintfW(&(errorString[0]), L"%u", status);
  128. CsLogEvent1(LOG_CRITICAL, CS_EVENT_ALLOCATION_FAILURE, errorString);
  129. ClRtlLogPrint(LOG_CRITICAL,
  130. "[NM] Unable to create network interface object type, %1!u!\n",
  131. status
  132. );
  133. }
  134. return(status);
  135. } // NmpInitializeInterfaces
  136. VOID
  137. NmpCleanupInterfaces(
  138. VOID
  139. )
  140. /*++
  141. Routine Description:
  142. Destroys all existing network interface resources.
  143. Arguments:
  144. None.
  145. Return Value:
  146. None.
  147. --*/
  148. {
  149. PNM_INTERFACE netInterface;
  150. PLIST_ENTRY entry;
  151. DWORD status;
  152. ClRtlLogPrint(
  153. LOG_NOISE,
  154. "[NM] Interface cleanup starting...\n"
  155. );
  156. //
  157. // Now clean up all the interface objects.
  158. //
  159. NmpAcquireLock();
  160. while (!IsListEmpty(&NmpInterfaceList)) {
  161. entry = RemoveHeadList(&NmpInterfaceList);
  162. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, Linkage);
  163. CL_ASSERT(NM_OM_INSERTED(netInterface));
  164. NmpDeleteInterfaceObject(netInterface, FALSE);
  165. }
  166. NmpReleaseLock();
  167. ClRtlLogPrint(LOG_NOISE,"[NM] Network interface cleanup complete\n");
  168. return;
  169. } // NmpCleanupInterfaces
  170. /////////////////////////////////////////////////////////////////////////////
  171. //
  172. // Top-level routines called during network configuration
  173. //
  174. /////////////////////////////////////////////////////////////////////////////
  175. DWORD
  176. NmpCreateInterface(
  177. IN RPC_BINDING_HANDLE JoinSponsorBinding,
  178. IN PNM_INTERFACE_INFO2 InterfaceInfo
  179. )
  180. /*++
  181. Notes:
  182. Must not be called with NM lock held.
  183. --*/
  184. {
  185. DWORD status;
  186. CL_ASSERT(InterfaceInfo->NetIndex == NmInvalidInterfaceNetIndex);
  187. if (JoinSponsorBinding != NULL) {
  188. //
  189. // We are joining a cluster. Ask the sponsor to do the dirty work.
  190. //
  191. status = NmRpcCreateInterface2(
  192. JoinSponsorBinding,
  193. NmpJoinSequence,
  194. NmLocalNodeIdString,
  195. InterfaceInfo
  196. );
  197. }
  198. else if (NmpState == NmStateOnlinePending) {
  199. HLOCALXSACTION xaction;
  200. //
  201. // We are forming a cluster. Add the definition directly to the
  202. // database. The corresponding object will be created later in
  203. // the form process.
  204. //
  205. //
  206. // Start a transaction - this must be done before acquiring the
  207. // NM lock.
  208. //
  209. xaction = DmBeginLocalUpdate();
  210. if (xaction == NULL) {
  211. status = GetLastError();
  212. ClRtlLogPrint(LOG_CRITICAL,
  213. "[NM] Failed to start a transaction, status %1!u!\n",
  214. status
  215. );
  216. return(status);
  217. }
  218. status = NmpCreateInterfaceDefinition(InterfaceInfo, xaction);
  219. //
  220. // Complete the transaction - this must be done after releasing
  221. // the NM lock.
  222. //
  223. if (status == ERROR_SUCCESS) {
  224. DmCommitLocalUpdate(xaction);
  225. }
  226. else {
  227. DmAbortLocalUpdate(xaction);
  228. }
  229. }
  230. else {
  231. //
  232. // We are online. This is a PnP update.
  233. //
  234. NmpAcquireLock();
  235. status = NmpGlobalCreateInterface(InterfaceInfo);
  236. NmpReleaseLock();
  237. }
  238. return(status);
  239. } // NmpCreateInterface
  240. DWORD
  241. NmpSetInterfaceInfo(
  242. IN RPC_BINDING_HANDLE JoinSponsorBinding,
  243. IN PNM_INTERFACE_INFO2 InterfaceInfo
  244. )
  245. /*++
  246. Notes:
  247. Must not be called with NM lock held.
  248. --*/
  249. {
  250. DWORD status;
  251. if (JoinSponsorBinding != NULL) {
  252. //
  253. // We are joining a cluster. Ask the sponsor to do the dirty work.
  254. //
  255. status = NmRpcSetInterfaceInfo2(
  256. JoinSponsorBinding,
  257. NmpJoinSequence,
  258. NmLocalNodeIdString,
  259. InterfaceInfo
  260. );
  261. }
  262. else if (NmpState == NmStateOnlinePending) {
  263. //
  264. // We are forming a cluster. Update the database directly.
  265. //
  266. HLOCALXSACTION xaction;
  267. //
  268. // Start a transaction - this must be done before acquiring the
  269. // NM lock.
  270. //
  271. xaction = DmBeginLocalUpdate();
  272. if (xaction == NULL) {
  273. status = GetLastError();
  274. ClRtlLogPrint(LOG_CRITICAL,
  275. "[NM] Failed to start a transaction, status %1!u!\n",
  276. status
  277. );
  278. return(status);
  279. }
  280. status = NmpSetInterfaceDefinition(InterfaceInfo, xaction);
  281. //
  282. // Complete the transaction - this must be done after releasing
  283. // the NM lock.
  284. //
  285. if (status == ERROR_SUCCESS) {
  286. DmCommitLocalUpdate(xaction);
  287. }
  288. else {
  289. DmAbortLocalUpdate(xaction);
  290. }
  291. }
  292. else {
  293. //
  294. // We are online. This is a PnP update.
  295. //
  296. NmpAcquireLock();
  297. status = NmpGlobalSetInterfaceInfo(InterfaceInfo);
  298. NmpReleaseLock();
  299. }
  300. return(status);
  301. } // NmpSetInterfaceInfo
  302. DWORD
  303. NmpDeleteInterface(
  304. IN RPC_BINDING_HANDLE JoinSponsorBinding,
  305. IN LPWSTR InterfaceId,
  306. IN LPWSTR NetworkId,
  307. IN OUT PBOOLEAN NetworkDeleted
  308. )
  309. /*++
  310. Notes:
  311. Must not be called with NM lock held.
  312. --*/
  313. {
  314. DWORD status;
  315. *NetworkDeleted = FALSE;
  316. if (JoinSponsorBinding != NULL) {
  317. //
  318. // We are joining a cluster. Ask the sponsor to perform the update.
  319. //
  320. status = NmRpcDeleteInterface(
  321. JoinSponsorBinding,
  322. NmpJoinSequence,
  323. NmLocalNodeIdString,
  324. InterfaceId,
  325. NetworkDeleted
  326. );
  327. }
  328. else if (NmpState == NmStateOnlinePending) {
  329. //
  330. // We are forming a cluster. Update the database directly.
  331. //
  332. HLOCALXSACTION xaction;
  333. //
  334. // Start a transaction - this must be done before acquiring the
  335. // NM lock.
  336. //
  337. xaction = DmBeginLocalUpdate();
  338. if (xaction == NULL) {
  339. status = GetLastError();
  340. ClRtlLogPrint(LOG_CRITICAL,
  341. "[NM] Failed to start a transaction, status %1!u!\n",
  342. status
  343. );
  344. return(status);
  345. }
  346. //
  347. // Delete the interface from the database.
  348. //
  349. status = DmLocalDeleteTree(xaction, DmNetInterfacesKey, InterfaceId);
  350. if (status == ERROR_SUCCESS) {
  351. PNM_INTERFACE_ENUM2 interfaceEnum = NULL;
  352. //
  353. // If this interface was the last one defined for the associated
  354. // network, delete the network.
  355. //
  356. status = NmpEnumInterfaceDefinitions(&interfaceEnum);
  357. if (status == ERROR_SUCCESS) {
  358. BOOLEAN deleteNetwork = TRUE;
  359. PNM_INTERFACE_INFO2 interfaceInfo;
  360. DWORD i;
  361. for (i=0; i<interfaceEnum->InterfaceCount; i++) {
  362. interfaceInfo = &(interfaceEnum->InterfaceList[i]);
  363. if (wcscmp(interfaceInfo->NetworkId, NetworkId) == 0) {
  364. deleteNetwork = FALSE;
  365. break;
  366. }
  367. }
  368. if (deleteNetwork) {
  369. status = DmLocalDeleteTree(
  370. xaction,
  371. DmNetworksKey,
  372. NetworkId
  373. );
  374. if (status == ERROR_SUCCESS) {
  375. *NetworkDeleted = TRUE;
  376. }
  377. }
  378. ClNetFreeInterfaceEnum(interfaceEnum);
  379. }
  380. }
  381. //
  382. // Complete the transaction - this must be done after releasing
  383. // the NM lock.
  384. //
  385. if (status == ERROR_SUCCESS) {
  386. DmCommitLocalUpdate(xaction);
  387. }
  388. else {
  389. DmAbortLocalUpdate(xaction);
  390. }
  391. }
  392. else {
  393. //
  394. // We are online. This is a PnP update.
  395. //
  396. NmpAcquireLock();
  397. status = NmpGlobalDeleteInterface(
  398. InterfaceId,
  399. NetworkDeleted
  400. );
  401. NmpReleaseLock();
  402. }
  403. return(status);
  404. } // NmpDeleteInterface
  405. /////////////////////////////////////////////////////////////////////////////
  406. //
  407. // Remote procedures called by active member nodes
  408. //
  409. /////////////////////////////////////////////////////////////////////////////
  410. error_status_t
  411. s_NmRpcReportInterfaceConnectivity(
  412. IN PRPC_ASYNC_STATE AsyncState,
  413. IN handle_t IDL_handle,
  414. IN LPWSTR InterfaceId,
  415. IN PNM_CONNECTIVITY_VECTOR ConnectivityVector
  416. )
  417. {
  418. PNM_INTERFACE netInterface;
  419. DWORD status = ERROR_SUCCESS;
  420. RPC_STATUS tempStatus;
  421. NmpAcquireLock();
  422. if (NmpLockedEnterApi(NmStateOnline)){
  423. netInterface = OmReferenceObjectById(
  424. ObjectTypeNetInterface,
  425. InterfaceId
  426. );
  427. if (netInterface != NULL) {
  428. ClRtlLogPrint(LOG_NOISE,
  429. "[NM] Received connectivity report from node %1!u! (interface %2!u!) for network %3!ws! (%4!ws!).\n",
  430. netInterface->Node->NodeId,
  431. netInterface->NetIndex,
  432. OmObjectId(netInterface->Network),
  433. OmObjectName(netInterface->Network)
  434. );
  435. NmpProcessInterfaceConnectivityReport(
  436. netInterface,
  437. ConnectivityVector
  438. );
  439. OmDereferenceObject(netInterface);
  440. }
  441. else {
  442. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  443. ClRtlLogPrint(LOG_UNUSUAL,
  444. "[NM] Received connectivity report from unknown interface %1!ws!.\n",
  445. InterfaceId
  446. );
  447. }
  448. NmpLockedLeaveApi();
  449. }
  450. else {
  451. status = ERROR_NODE_NOT_AVAILABLE;
  452. ClRtlLogPrint(LOG_NOISE,
  453. "[NM] Not in valid state to process connectivity report.\n"
  454. );
  455. }
  456. NmpReleaseLock();
  457. tempStatus = RpcAsyncCompleteCall(AsyncState, &status);
  458. if(tempStatus != RPC_S_OK)
  459. ClRtlLogPrint(LOG_UNUSUAL,
  460. "[NM] s_NmRpcReportInterfaceConnectivity(), Error Completing Async RPC call, status %1!u!\n",
  461. tempStatus
  462. );
  463. return(status);
  464. } // s_NmRpcReportInterfaceConnectivity
  465. error_status_t
  466. s_NmRpcGetInterfaceOnlineAddressEnum(
  467. IN handle_t IDL_handle,
  468. IN LPWSTR InterfaceId,
  469. OUT PNM_ADDRESS_ENUM * OnlineAddressEnum
  470. )
  471. {
  472. PNM_INTERFACE netInterface;
  473. DWORD status = ERROR_SUCCESS;
  474. ClRtlLogPrint(LOG_NOISE,
  475. "[NM] Received request to get online address enum for interface %1!ws!.\n",
  476. InterfaceId
  477. );
  478. *OnlineAddressEnum = NULL;
  479. NmpAcquireLock();
  480. if (NmpLockedEnterApi(NmStateOnline)){
  481. netInterface = OmReferenceObjectById(ObjectTypeNetInterface, InterfaceId);
  482. if (netInterface != NULL) {
  483. status = NmpBuildInterfaceOnlineAddressEnum(
  484. netInterface,
  485. OnlineAddressEnum
  486. );
  487. OmDereferenceObject(netInterface);
  488. }
  489. else {
  490. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  491. ClRtlLogPrint(LOG_UNUSUAL,
  492. "[NM] GetInterfaceOnlineAddressEnum: interface %1!ws! doesn't exist.\n",
  493. InterfaceId
  494. );
  495. }
  496. NmpLockedLeaveApi();
  497. }
  498. else {
  499. status = ERROR_NODE_NOT_AVAILABLE;
  500. ClRtlLogPrint(LOG_NOISE,
  501. "[NM] Not in valid state to process GetInterfaceOnlineAddressEnum request.\n"
  502. );
  503. }
  504. NmpReleaseLock();
  505. return(status);
  506. } // s_NmRpcGetInterfaceOnlineAddressEnum
  507. error_status_t
  508. s_NmRpcGetInterfacePingAddressEnum(
  509. IN handle_t IDL_handle,
  510. IN LPWSTR InterfaceId,
  511. IN PNM_ADDRESS_ENUM OnlineAddressEnum,
  512. OUT PNM_ADDRESS_ENUM * PingAddressEnum
  513. )
  514. {
  515. PNM_INTERFACE netInterface;
  516. DWORD status = ERROR_SUCCESS;
  517. ClRtlLogPrint(LOG_NOISE,
  518. "[NM] Received request to get ping address enum for interface %1!ws!.\n",
  519. InterfaceId
  520. );
  521. *PingAddressEnum = NULL;
  522. NmpAcquireLock();
  523. if (NmpLockedEnterApi(NmStateOnline)){
  524. netInterface = OmReferenceObjectById(ObjectTypeNetInterface, InterfaceId);
  525. if (netInterface != NULL) {
  526. status = NmpBuildInterfacePingAddressEnum(
  527. netInterface,
  528. OnlineAddressEnum,
  529. PingAddressEnum
  530. );
  531. OmDereferenceObject(netInterface);
  532. }
  533. else {
  534. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  535. ClRtlLogPrint(LOG_UNUSUAL,
  536. "[NM] GetInterfacePingAddressEnum: interface %1!ws! doesn't exist.\n",
  537. InterfaceId
  538. );
  539. }
  540. NmpLockedLeaveApi();
  541. }
  542. else {
  543. status = ERROR_NODE_NOT_AVAILABLE;
  544. ClRtlLogPrint(LOG_NOISE,
  545. "[NM] Not in valid state to process GetInterfacePingAddressEnum request.\n"
  546. );
  547. }
  548. NmpReleaseLock();
  549. return(status);
  550. } // s_NmRpcGetInterfacePingAddressEnum
  551. //
  552. // Note: s_NmRpcDoInterfacePing returns void rather than CallStatus
  553. // due to a MIDL compiler error in an early beta of W2K. Since
  554. // the CallStatus is the final parameter, the format on the
  555. // wire is the same; however, the call works in its current
  556. // format, so there is no point in changing it now.
  557. //
  558. void
  559. s_NmRpcDoInterfacePing(
  560. IN PRPC_ASYNC_STATE AsyncState,
  561. IN handle_t IDL_handle,
  562. IN LPWSTR InterfaceId,
  563. IN PNM_ADDRESS_ENUM PingAddressEnum,
  564. OUT BOOLEAN * PingSucceeded,
  565. OUT error_status_t * CallStatus
  566. )
  567. {
  568. DWORD status = ERROR_SUCCESS;
  569. RPC_STATUS tempStatus;
  570. ClRtlLogPrint(LOG_NOISE,
  571. "[NM] Received request to ping targets for interface %1!ws!.\n",
  572. InterfaceId
  573. );
  574. *PingSucceeded = FALSE;
  575. NmpAcquireLock();
  576. if (NmpLockedEnterApi(NmStateOnline)){
  577. PNM_INTERFACE netInterface = OmReferenceObjectById(
  578. ObjectTypeNetInterface,
  579. InterfaceId
  580. );
  581. if (netInterface != NULL) {
  582. PNM_NETWORK network = netInterface->Network;
  583. if ( (network->LocalInterface == netInterface) &&
  584. NmpIsNetworkRegistered(network)
  585. )
  586. {
  587. NmpReleaseLock();
  588. status = NmpDoInterfacePing(
  589. netInterface,
  590. PingAddressEnum,
  591. PingSucceeded
  592. );
  593. NmpAcquireLock();
  594. }
  595. else {
  596. status = ERROR_INVALID_PARAMETER;
  597. ClRtlLogPrint(LOG_UNUSUAL,
  598. "[NM] RpcDoInterfacePing: interface %1!ws! isn't local.\n",
  599. InterfaceId
  600. );
  601. }
  602. OmDereferenceObject(netInterface);
  603. }
  604. else {
  605. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  606. ClRtlLogPrint(LOG_UNUSUAL,
  607. "[NM] RpcDoInterfacePing: interface %1!ws! doesn't exist.\n",
  608. InterfaceId
  609. );
  610. }
  611. NmpLockedLeaveApi();
  612. }
  613. else {
  614. status = ERROR_NODE_NOT_AVAILABLE;
  615. ClRtlLogPrint(LOG_NOISE,
  616. "[NM] Not in valid state to process RpcDoInterfacePing request.\n"
  617. );
  618. }
  619. ClRtlLogPrint(LOG_NOISE,
  620. "[NM] Finished pinging targets for interface %1!ws!.\n",
  621. InterfaceId
  622. );
  623. NmpReleaseLock();
  624. *CallStatus = status;
  625. tempStatus = RpcAsyncCompleteCall(AsyncState, NULL);
  626. if(tempStatus != RPC_S_OK)
  627. ClRtlLogPrint(LOG_UNUSUAL,
  628. "[NM] s_NmRpcDoInterfacePing() Failed to complete Async RPC call, status %1!u!\n",
  629. tempStatus
  630. );
  631. return;
  632. } // s_NmRpcDoInterfacePing
  633. /////////////////////////////////////////////////////////////////////////////
  634. //
  635. // Remote procedures called by joining nodes
  636. //
  637. /////////////////////////////////////////////////////////////////////////////
  638. error_status_t
  639. s_NmRpcCreateInterface(
  640. IN handle_t IDL_handle,
  641. IN DWORD JoinSequence, OPTIONAL
  642. IN LPWSTR JoinerNodeId, OPTIONAL
  643. IN PNM_INTERFACE_INFO InterfaceInfo1
  644. )
  645. {
  646. DWORD status;
  647. NM_INTERFACE_INFO2 interfaceInfo2;
  648. //
  649. // Translate and call the V2.0 procedure.
  650. //
  651. CopyMemory(&interfaceInfo2, InterfaceInfo1, sizeof(NM_INTERFACE_INFO));
  652. //
  653. // The NetIndex isn't used in this call.
  654. //
  655. interfaceInfo2.NetIndex = NmInvalidInterfaceNetIndex;
  656. //
  657. // Use the unknown string for the adapter ID.
  658. //
  659. interfaceInfo2.AdapterId = NmpUnknownString;
  660. status = s_NmRpcCreateInterface2(
  661. IDL_handle,
  662. JoinSequence,
  663. JoinerNodeId,
  664. &interfaceInfo2
  665. );
  666. return(status);
  667. } // s_NmRpcCreateInterface
  668. error_status_t
  669. s_NmRpcCreateInterface2(
  670. IN handle_t IDL_handle,
  671. IN DWORD JoinSequence, OPTIONAL
  672. IN LPWSTR JoinerNodeId, OPTIONAL
  673. IN PNM_INTERFACE_INFO2 InterfaceInfo2
  674. )
  675. {
  676. DWORD status = ERROR_SUCCESS;
  677. NmpAcquireLock();
  678. if (NmpLockedEnterApi(NmStateOnline)) {
  679. PNM_NODE joinerNode = NULL;
  680. ClRtlLogPrint(LOG_NOISE,
  681. "[NMJOIN] Processing request to create new interface %1!ws! for joining node.\n",
  682. InterfaceInfo2->Id
  683. );
  684. if (lstrcmpW(JoinerNodeId, NmpInvalidJoinerIdString) != 0) {
  685. joinerNode = OmReferenceObjectById(
  686. ObjectTypeNode,
  687. JoinerNodeId
  688. );
  689. if (joinerNode != NULL) {
  690. if ( (JoinSequence == NmpJoinSequence) &&
  691. (NmpJoinerNodeId == joinerNode->NodeId) &&
  692. (NmpSponsorNodeId == NmLocalNodeId) &&
  693. !NmpJoinAbortPending
  694. )
  695. {
  696. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  697. CL_ASSERT(NmpJoinerUp == FALSE);
  698. CL_ASSERT(NmpJoinTimer != 0);
  699. //
  700. // Suspend the join timer while we are working on
  701. // behalf of the joiner. This precludes an abort
  702. // from occuring as well.
  703. //
  704. NmpJoinTimer = 0;
  705. }
  706. else {
  707. status = ERROR_CLUSTER_JOIN_ABORTED;
  708. ClRtlLogPrint(LOG_UNUSUAL,
  709. "[NMJOIN] CreateInterface call for joining node %1!ws! failed because the join was aborted.\n",
  710. JoinerNodeId
  711. );
  712. }
  713. }
  714. else {
  715. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  716. ClRtlLogPrint(LOG_UNUSUAL,
  717. "[NMJOIN] CreateInterface call for joining node %1!ws! failed because the node is not a member of the cluster.\n",
  718. JoinerNodeId
  719. );
  720. }
  721. }
  722. if (status == ERROR_SUCCESS) {
  723. CL_ASSERT(InterfaceInfo2->NetIndex == NmInvalidInterfaceNetIndex);
  724. //
  725. // Just to be safe
  726. //
  727. InterfaceInfo2->NetIndex = NmInvalidInterfaceNetIndex;
  728. status = NmpGlobalCreateInterface(InterfaceInfo2);
  729. if (joinerNode != NULL) {
  730. //
  731. // Verify that the join is still in progress
  732. //
  733. if ( (JoinSequence == NmpJoinSequence) &&
  734. (NmpJoinerNodeId == joinerNode->NodeId)
  735. )
  736. {
  737. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  738. CL_ASSERT(NmpJoinerUp == FALSE);
  739. CL_ASSERT(NmpSponsorNodeId == NmLocalNodeId);
  740. CL_ASSERT(NmpJoinTimer == 0);
  741. CL_ASSERT(NmpJoinAbortPending == FALSE);
  742. if (status == ERROR_SUCCESS) {
  743. //
  744. // Restart the join timer.
  745. //
  746. NmpJoinTimer = NM_JOIN_TIMEOUT;
  747. }
  748. else {
  749. //
  750. // Abort the join
  751. //
  752. NmpJoinAbort(status, joinerNode);
  753. }
  754. }
  755. else {
  756. status = ERROR_CLUSTER_JOIN_ABORTED;
  757. ClRtlLogPrint(LOG_UNUSUAL,
  758. "[NMJOIN] CreateInterface call for joining node %1!ws! failed because the join was aborted.\n",
  759. JoinerNodeId
  760. );
  761. }
  762. }
  763. }
  764. if (joinerNode != NULL) {
  765. OmDereferenceObject(joinerNode);
  766. }
  767. NmpLockedLeaveApi();
  768. }
  769. else {
  770. status = ERROR_NODE_NOT_AVAILABLE;
  771. ClRtlLogPrint(LOG_NOISE,
  772. "[NMJOIN] Not in valid state to process CreateInterface request.\n"
  773. );
  774. }
  775. NmpReleaseLock();
  776. return(status);
  777. } // s_NmRpcCreateInterface2
  778. error_status_t
  779. s_NmRpcSetInterfaceInfo(
  780. IN handle_t IDL_handle,
  781. IN DWORD JoinSequence, OPTIONAL
  782. IN LPWSTR JoinerNodeId, OPTIONAL
  783. IN PNM_INTERFACE_INFO InterfaceInfo1
  784. )
  785. {
  786. DWORD status;
  787. NM_INTERFACE_INFO2 interfaceInfo2;
  788. //
  789. // Translate and call the V2.0 procedure.
  790. //
  791. CopyMemory(&interfaceInfo2, InterfaceInfo1, sizeof(NM_INTERFACE_INFO));
  792. //
  793. // The NetIndex is not used in this call.
  794. //
  795. interfaceInfo2.NetIndex = NmInvalidInterfaceNetIndex;
  796. //
  797. // Use the unknown string for the adapter ID.
  798. //
  799. interfaceInfo2.AdapterId = NmpUnknownString;
  800. status = s_NmRpcSetInterfaceInfo2(
  801. IDL_handle,
  802. JoinSequence,
  803. JoinerNodeId,
  804. &interfaceInfo2
  805. );
  806. return(status);
  807. } // s_NmRpcSetInterfaceInfo
  808. error_status_t
  809. s_NmRpcSetInterfaceInfo2(
  810. IN handle_t IDL_handle,
  811. IN DWORD JoinSequence, OPTIONAL
  812. IN LPWSTR JoinerNodeId, OPTIONAL
  813. IN PNM_INTERFACE_INFO2 InterfaceInfo2
  814. )
  815. {
  816. DWORD status = ERROR_SUCCESS;
  817. NmpAcquireLock();
  818. if (NmpLockedEnterApi(NmStateOnline)) {
  819. PNM_NODE joinerNode = NULL;
  820. ClRtlLogPrint(LOG_NOISE,
  821. "[NMJOIN] Processing request to set info for interface %1!ws! for joining node.\n",
  822. InterfaceInfo2->Id
  823. );
  824. if (lstrcmpW(JoinerNodeId, NmpInvalidJoinerIdString) != 0) {
  825. joinerNode = OmReferenceObjectById(
  826. ObjectTypeNode,
  827. JoinerNodeId
  828. );
  829. if (joinerNode != NULL) {
  830. if ( (JoinSequence == NmpJoinSequence) &&
  831. (NmpJoinerNodeId == joinerNode->NodeId) &&
  832. (NmpSponsorNodeId == NmLocalNodeId) &&
  833. !NmpJoinAbortPending
  834. )
  835. {
  836. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  837. CL_ASSERT(NmpJoinerUp == FALSE);
  838. CL_ASSERT(NmpJoinTimer != 0);
  839. //
  840. // Suspend the join timer while we are working on
  841. // behalf of the joiner. This precludes an abort
  842. // from occuring as well.
  843. //
  844. NmpJoinTimer = 0;
  845. }
  846. else {
  847. status = ERROR_CLUSTER_JOIN_ABORTED;
  848. ClRtlLogPrint(LOG_UNUSUAL,
  849. "[NMJOIN] SetInterfaceInfo call for joining node %1!ws! failed because the join was aborted.\n",
  850. JoinerNodeId
  851. );
  852. }
  853. }
  854. else {
  855. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  856. ClRtlLogPrint(LOG_UNUSUAL,
  857. "[NMJOIN] SetInterfaceInfo call for joining node %1!ws! failed because the node is not a member of the cluster.\n",
  858. JoinerNodeId
  859. );
  860. }
  861. }
  862. if (status == ERROR_SUCCESS) {
  863. status = NmpGlobalSetInterfaceInfo(InterfaceInfo2);
  864. if (joinerNode != NULL) {
  865. //
  866. // Verify that the join is still in progress
  867. //
  868. if ( (JoinSequence == NmpJoinSequence) &&
  869. (NmpJoinerNodeId == joinerNode->NodeId)
  870. )
  871. {
  872. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  873. CL_ASSERT(NmpJoinerUp == FALSE);
  874. CL_ASSERT(NmpSponsorNodeId == NmLocalNodeId);
  875. CL_ASSERT(NmpJoinTimer == 0);
  876. CL_ASSERT(NmpJoinAbortPending == FALSE);
  877. if (status == ERROR_SUCCESS) {
  878. //
  879. // Restart the join timer.
  880. //
  881. NmpJoinTimer = NM_JOIN_TIMEOUT;
  882. }
  883. else {
  884. //
  885. // Abort the join
  886. //
  887. NmpJoinAbort(status, joinerNode);
  888. }
  889. }
  890. else {
  891. status = ERROR_CLUSTER_JOIN_ABORTED;
  892. ClRtlLogPrint(LOG_UNUSUAL,
  893. "[NMJOIN] SetInterfaceInfo call for joining node %1!ws! failed because the join was aborted.\n",
  894. JoinerNodeId
  895. );
  896. }
  897. }
  898. }
  899. if (joinerNode != NULL) {
  900. OmDereferenceObject(joinerNode);
  901. }
  902. NmpLockedLeaveApi();
  903. }
  904. else {
  905. status = ERROR_NODE_NOT_AVAILABLE;
  906. ClRtlLogPrint(LOG_NOISE,
  907. "[NMJOIN] Not in valid state to process SetInterfaceInfo request.\n"
  908. );
  909. }
  910. NmpReleaseLock();
  911. return(status);
  912. } // s_NmRpcSetInterfaceInfo2
  913. error_status_t
  914. s_NmRpcDeleteInterface(
  915. IN handle_t IDL_handle,
  916. IN DWORD JoinSequence, OPTIONAL
  917. IN LPWSTR JoinerNodeId, OPTIONAL
  918. IN LPWSTR InterfaceId,
  919. OUT BOOLEAN * NetworkDeleted
  920. )
  921. {
  922. DWORD status = ERROR_SUCCESS;
  923. NmpAcquireLock();
  924. if (NmpLockedEnterApi(NmStateOnline)) {
  925. PNM_NODE joinerNode = NULL;
  926. ClRtlLogPrint(LOG_NOISE,
  927. "[NMJOIN] Processing request to delete interface %1!ws! for joining node.\n",
  928. InterfaceId
  929. );
  930. if (lstrcmpW(JoinerNodeId, NmpInvalidJoinerIdString) != 0) {
  931. joinerNode = OmReferenceObjectById(
  932. ObjectTypeNode,
  933. JoinerNodeId
  934. );
  935. if (joinerNode != NULL) {
  936. if ( (JoinSequence == NmpJoinSequence) &&
  937. (NmpJoinerNodeId == joinerNode->NodeId) &&
  938. (NmpSponsorNodeId == NmLocalNodeId) &&
  939. !NmpJoinAbortPending
  940. )
  941. {
  942. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  943. CL_ASSERT(NmpJoinerUp == FALSE);
  944. CL_ASSERT(NmpJoinTimer != 0);
  945. //
  946. // Suspend the join timer while we are working on
  947. // behalf of the joiner. This precludes an abort
  948. // from occuring as well.
  949. //
  950. NmpJoinTimer = 0;
  951. }
  952. else {
  953. status = ERROR_CLUSTER_JOIN_ABORTED;
  954. ClRtlLogPrint(LOG_UNUSUAL,
  955. "[NMJOIN] DeleteInterface call for joining node %1!ws! failed because the join was aborted.\n",
  956. JoinerNodeId
  957. );
  958. }
  959. }
  960. else {
  961. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  962. ClRtlLogPrint(LOG_UNUSUAL,
  963. "[NMJOIN] DeleteInterface call for joining node %1!ws! failed because the node is not a member of the cluster.\n",
  964. JoinerNodeId
  965. );
  966. }
  967. }
  968. if (status == ERROR_SUCCESS) {
  969. status = NmpGlobalDeleteInterface(
  970. InterfaceId,
  971. NetworkDeleted
  972. );
  973. if (joinerNode != NULL) {
  974. //
  975. // Verify that the join is still in progress
  976. //
  977. if ( (JoinSequence == NmpJoinSequence) &&
  978. (NmpJoinerNodeId == joinerNode->NodeId)
  979. )
  980. {
  981. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  982. CL_ASSERT(NmpJoinerUp == FALSE);
  983. CL_ASSERT(NmpSponsorNodeId == NmLocalNodeId);
  984. CL_ASSERT(NmpJoinTimer == 0);
  985. CL_ASSERT(NmpJoinAbortPending == FALSE);
  986. if (status == ERROR_SUCCESS) {
  987. //
  988. // Restart the join timer.
  989. //
  990. NmpJoinTimer = NM_JOIN_TIMEOUT;
  991. }
  992. else {
  993. //
  994. // Abort the join
  995. //
  996. NmpJoinAbort(status, joinerNode);
  997. }
  998. }
  999. else {
  1000. status = ERROR_CLUSTER_JOIN_ABORTED;
  1001. ClRtlLogPrint(LOG_UNUSUAL,
  1002. "[NMJOIN] DeleteInterface call for joining node %1!ws! failed because the join was aborted.\n",
  1003. JoinerNodeId
  1004. );
  1005. }
  1006. }
  1007. }
  1008. if (joinerNode != NULL) {
  1009. OmDereferenceObject(joinerNode);
  1010. }
  1011. NmpLockedLeaveApi();
  1012. }
  1013. else {
  1014. status = ERROR_NODE_NOT_AVAILABLE;
  1015. ClRtlLogPrint(LOG_NOISE,
  1016. "[NMJOIN] Not in valid state to process DeleteInterface request.\n"
  1017. );
  1018. }
  1019. NmpReleaseLock();
  1020. return(status);
  1021. } // s_NmRpcDeleteInterface
  1022. error_status_t
  1023. NmpEnumInterfaceDefinitionsForJoiner(
  1024. IN DWORD JoinSequence, OPTIONAL
  1025. IN LPWSTR JoinerNodeId, OPTIONAL
  1026. OUT PNM_INTERFACE_ENUM * InterfaceEnum1,
  1027. OUT PNM_INTERFACE_ENUM2 * InterfaceEnum2
  1028. )
  1029. {
  1030. DWORD status = ERROR_SUCCESS;
  1031. PNM_NODE joinerNode = NULL;
  1032. NmpAcquireLock();
  1033. if (NmpLockedEnterApi(NmStateOnline)) {
  1034. ClRtlLogPrint(LOG_NOISE,
  1035. "[NMJOIN] Supplying interface information to joining node.\n"
  1036. );
  1037. if (lstrcmpW(JoinerNodeId, NmpInvalidJoinerIdString) != 0) {
  1038. joinerNode = OmReferenceObjectById(
  1039. ObjectTypeNode,
  1040. JoinerNodeId
  1041. );
  1042. if (joinerNode != NULL) {
  1043. if ( (JoinSequence == NmpJoinSequence) &&
  1044. (NmpJoinerNodeId == joinerNode->NodeId) &&
  1045. (NmpSponsorNodeId == NmLocalNodeId) &&
  1046. !NmpJoinAbortPending
  1047. )
  1048. {
  1049. CL_ASSERT(joinerNode->State == ClusterNodeJoining);
  1050. CL_ASSERT(NmpJoinerUp == FALSE);
  1051. CL_ASSERT(NmpJoinTimer != 0);
  1052. //
  1053. // Suspend the join timer while we are working on
  1054. // behalf of the joiner. This precludes an abort
  1055. // from occuring as well.
  1056. //
  1057. NmpJoinTimer = 0;
  1058. }
  1059. else {
  1060. status = ERROR_CLUSTER_JOIN_ABORTED;
  1061. ClRtlLogPrint(LOG_UNUSUAL,
  1062. "[NMJOIN] EnumInterfaceDefinitions call for joining node %1!ws! failed because the join was aborted.\n",
  1063. JoinerNodeId
  1064. );
  1065. }
  1066. }
  1067. else {
  1068. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  1069. ClRtlLogPrint(LOG_UNUSUAL,
  1070. "[NMJOIN] EnumInterfaceDefinitions call for joining node %1!ws! failed because the node is not a member of the cluster.\n",
  1071. JoinerNodeId
  1072. );
  1073. }
  1074. }
  1075. if (status == ERROR_SUCCESS) {
  1076. if (InterfaceEnum1 != NULL) {
  1077. status = NmpEnumInterfaceObjects1(InterfaceEnum1);
  1078. }
  1079. else {
  1080. CL_ASSERT(InterfaceEnum2 != NULL);
  1081. status = NmpEnumInterfaceObjects(InterfaceEnum2);
  1082. }
  1083. if (joinerNode != NULL) {
  1084. if (status == ERROR_SUCCESS) {
  1085. //
  1086. // Restart the join timer.
  1087. //
  1088. NmpJoinTimer = NM_JOIN_TIMEOUT;
  1089. }
  1090. else {
  1091. ClRtlLogPrint(LOG_CRITICAL,
  1092. "[NMJOIN] EnumInterfaceDefinitions failed, status %1!u!.\n",
  1093. status
  1094. );
  1095. //
  1096. // Abort the join
  1097. //
  1098. NmpJoinAbort(status, joinerNode);
  1099. }
  1100. }
  1101. }
  1102. if (joinerNode != NULL) {
  1103. OmDereferenceObject(joinerNode);
  1104. }
  1105. NmpLockedLeaveApi();
  1106. }
  1107. else {
  1108. status = ERROR_NODE_NOT_AVAILABLE;
  1109. ClRtlLogPrint(LOG_NOISE,
  1110. "[NMJOIN] Not in valid state to process EnumInterfaceDefinitions request.\n"
  1111. );
  1112. }
  1113. NmpReleaseLock();
  1114. return(status);
  1115. } // NmpEnumInterfaceDefinitionsForJoiner
  1116. error_status_t
  1117. s_NmRpcEnumInterfaceDefinitions(
  1118. IN handle_t IDL_handle,
  1119. IN DWORD JoinSequence, OPTIONAL
  1120. IN LPWSTR JoinerNodeId, OPTIONAL
  1121. OUT PNM_INTERFACE_ENUM * InterfaceEnum1
  1122. )
  1123. {
  1124. error_status_t status;
  1125. status = NmpEnumInterfaceDefinitionsForJoiner(
  1126. JoinSequence,
  1127. JoinerNodeId,
  1128. InterfaceEnum1,
  1129. NULL
  1130. );
  1131. return(status);
  1132. } // s_NmRpcEnumInterfaceDefinitions
  1133. error_status_t
  1134. s_NmRpcEnumInterfaceDefinitions2(
  1135. IN handle_t IDL_handle,
  1136. IN DWORD JoinSequence, OPTIONAL
  1137. IN LPWSTR JoinerNodeId, OPTIONAL
  1138. OUT PNM_INTERFACE_ENUM2 * InterfaceEnum2
  1139. )
  1140. {
  1141. error_status_t status;
  1142. status = NmpEnumInterfaceDefinitionsForJoiner(
  1143. JoinSequence,
  1144. JoinerNodeId,
  1145. NULL,
  1146. InterfaceEnum2
  1147. );
  1148. return(status);
  1149. } // s_NmRpcEnumInterfaceDefinitions2
  1150. error_status_t
  1151. s_NmRpcReportJoinerInterfaceConnectivity(
  1152. IN handle_t IDL_handle,
  1153. IN DWORD JoinSequence,
  1154. IN LPWSTR JoinerNodeId,
  1155. IN LPWSTR InterfaceId,
  1156. IN PNM_CONNECTIVITY_VECTOR ConnectivityVector
  1157. )
  1158. {
  1159. DWORD status = ERROR_SUCCESS;
  1160. NmpAcquireLock();
  1161. if (NmpLockedEnterApi(NmStateOnline)){
  1162. PNM_NODE joinerNode = OmReferenceObjectById(
  1163. ObjectTypeNode,
  1164. JoinerNodeId
  1165. );
  1166. if (joinerNode != NULL) {
  1167. //
  1168. // If the node is still joining, forward the report to the
  1169. // leader. Note that reports may race with the node transitioning
  1170. // to the up state, so accept reports from up nodes as well.
  1171. //
  1172. if ( ( (JoinSequence == NmpJoinSequence) &&
  1173. (NmpJoinerNodeId == joinerNode->NodeId) &&
  1174. (NmpSponsorNodeId == NmLocalNodeId) &&
  1175. !NmpJoinAbortPending
  1176. )
  1177. ||
  1178. NM_NODE_UP(joinerNode)
  1179. )
  1180. {
  1181. PNM_INTERFACE netInterface = OmReferenceObjectById(
  1182. ObjectTypeNetInterface,
  1183. InterfaceId
  1184. );
  1185. if (netInterface != NULL) {
  1186. PNM_NETWORK network = netInterface->Network;
  1187. LPCWSTR networkId = OmObjectId(network);
  1188. if (NmpLeaderNodeId == NmLocalNodeId) {
  1189. //
  1190. // This node is the leader. Process the report.
  1191. //
  1192. ClRtlLogPrint(LOG_NOISE,
  1193. "[NM] Processing connectivity report from joiner"
  1194. "node %1!ws! for network %2!ws!.\n",
  1195. JoinerNodeId,
  1196. networkId
  1197. );
  1198. NmpProcessInterfaceConnectivityReport(
  1199. netInterface,
  1200. ConnectivityVector
  1201. );
  1202. }
  1203. else {
  1204. //
  1205. // Forward the report to the leader.
  1206. //
  1207. RPC_BINDING_HANDLE binding;
  1208. ClRtlLogPrint(LOG_NOISE,
  1209. "[NM] Forwarding connectivity report from joiner "
  1210. "node %1!ws! for network %2!ws! to leader.\n",
  1211. JoinerNodeId,
  1212. networkId
  1213. );
  1214. binding = Session[NmpLeaderNodeId];
  1215. CL_ASSERT(binding != NULL);
  1216. OmReferenceObject(network);
  1217. status = NmpReportInterfaceConnectivity(
  1218. binding,
  1219. InterfaceId,
  1220. ConnectivityVector,
  1221. (LPWSTR) networkId
  1222. );
  1223. if (status != ERROR_SUCCESS) {
  1224. ClRtlLogPrint(LOG_UNUSUAL,
  1225. "[NM] Failed to forward connectivity report "
  1226. "from joiner node %1!ws! for network %2!ws!"
  1227. "to leader, status %3!u!\n",
  1228. JoinerNodeId,
  1229. networkId,
  1230. status
  1231. );
  1232. }
  1233. OmDereferenceObject(network);
  1234. }
  1235. OmDereferenceObject(netInterface);
  1236. }
  1237. else {
  1238. ClRtlLogPrint(LOG_UNUSUAL,
  1239. "[NMJOIN] Rejecting connectivity report from joining "
  1240. "node %1!ws! because interface %2!ws! does not "
  1241. "exist.\n",
  1242. JoinerNodeId,
  1243. InterfaceId
  1244. );
  1245. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  1246. }
  1247. }
  1248. else {
  1249. status = ERROR_CLUSTER_JOIN_ABORTED;
  1250. ClRtlLogPrint(LOG_UNUSUAL,
  1251. "[NMJOIN] Ignoring connectivity report from joining "
  1252. "node %1!ws! because the join was aborted.\n",
  1253. JoinerNodeId
  1254. );
  1255. }
  1256. OmDereferenceObject(joinerNode);
  1257. }
  1258. else {
  1259. status = ERROR_CLUSTER_NODE_NOT_MEMBER;
  1260. ClRtlLogPrint(LOG_UNUSUAL,
  1261. "[NMJOIN] Ignoring connectivity report from joining node "
  1262. "%1!ws! because the joiner is not a member of the cluster.\n",
  1263. JoinerNodeId
  1264. );
  1265. }
  1266. NmpLockedLeaveApi();
  1267. }
  1268. else {
  1269. status = ERROR_NODE_NOT_AVAILABLE;
  1270. ClRtlLogPrint(LOG_NOISE,
  1271. "[NMJOIN] Not in valid state to process connectivity report "
  1272. "from joiner node %1!ws!.\n",
  1273. JoinerNodeId
  1274. );
  1275. }
  1276. NmpReleaseLock();
  1277. return(status);
  1278. } // s_NmRpcReportJoinerInterfaceConnectivity
  1279. /////////////////////////////////////////////////////////////////////////////
  1280. //
  1281. // Routines used to make global configuration changes when the node
  1282. // is online.
  1283. //
  1284. /////////////////////////////////////////////////////////////////////////////
  1285. DWORD
  1286. NmpGlobalCreateInterface(
  1287. IN PNM_INTERFACE_INFO2 InterfaceInfo
  1288. )
  1289. /*++
  1290. Notes:
  1291. Called with the NmpLock held.
  1292. --*/
  1293. {
  1294. DWORD status;
  1295. DWORD interfacePropertiesSize;
  1296. PVOID interfaceProperties;
  1297. ClRtlLogPrint(LOG_NOISE,
  1298. "[NM] Issuing global update to create interface %1!ws!.\n",
  1299. InterfaceInfo->Id
  1300. );
  1301. //
  1302. // Marshall the info structures into property lists.
  1303. //
  1304. status = NmpMarshallObjectInfo(
  1305. NmpInterfaceProperties,
  1306. InterfaceInfo,
  1307. &interfaceProperties,
  1308. &interfacePropertiesSize
  1309. );
  1310. if (status == ERROR_SUCCESS) {
  1311. NmpReleaseLock();
  1312. //
  1313. // Issue a global update
  1314. //
  1315. status = GumSendUpdateEx(
  1316. GumUpdateMembership,
  1317. NmUpdateCreateInterface,
  1318. 2,
  1319. interfacePropertiesSize,
  1320. interfaceProperties,
  1321. sizeof(interfacePropertiesSize),
  1322. &interfacePropertiesSize
  1323. );
  1324. if (status != ERROR_SUCCESS) {
  1325. ClRtlLogPrint(LOG_CRITICAL,
  1326. "[NM] Global update to create interface %1!ws! failed, status %2!u!.\n",
  1327. InterfaceInfo->Id,
  1328. status
  1329. );
  1330. }
  1331. MIDL_user_free(interfaceProperties);
  1332. NmpAcquireLock();
  1333. }
  1334. else {
  1335. ClRtlLogPrint(LOG_CRITICAL,
  1336. "[NM] Failed to marshall properties for new interface %1!ws!, status %2!u!\n",
  1337. InterfaceInfo->Id,
  1338. status
  1339. );
  1340. }
  1341. return(status);
  1342. } // NmpGlobalCreateInterface
  1343. DWORD
  1344. NmpGlobalSetInterfaceInfo(
  1345. IN PNM_INTERFACE_INFO2 InterfaceInfo
  1346. )
  1347. /*++
  1348. Notes:
  1349. Called with the NmpLock held.
  1350. --*/
  1351. {
  1352. DWORD status = ERROR_SUCCESS;
  1353. DWORD interfacePropertiesSize;
  1354. PVOID interfaceProperties;
  1355. ClRtlLogPrint(LOG_NOISE,
  1356. "[NM] Issuing global update to set info for interface %1!ws!.\n",
  1357. InterfaceInfo->Id
  1358. );
  1359. //
  1360. // Marshall the info structures into property lists.
  1361. //
  1362. status = NmpMarshallObjectInfo(
  1363. NmpInterfaceProperties,
  1364. InterfaceInfo,
  1365. &interfaceProperties,
  1366. &interfacePropertiesSize
  1367. );
  1368. if (status == ERROR_SUCCESS) {
  1369. NmpReleaseLock();
  1370. //
  1371. // Issue a global update
  1372. //
  1373. status = GumSendUpdateEx(
  1374. GumUpdateMembership,
  1375. NmUpdateSetInterfaceInfo,
  1376. 2,
  1377. interfacePropertiesSize,
  1378. interfaceProperties,
  1379. sizeof(interfacePropertiesSize),
  1380. &interfacePropertiesSize
  1381. );
  1382. if (status != ERROR_SUCCESS) {
  1383. ClRtlLogPrint(LOG_CRITICAL,
  1384. "[NM] Global update to set properties for interface %1!ws! failed, status %2!u!.\n",
  1385. InterfaceInfo->Id,
  1386. status
  1387. );
  1388. }
  1389. MIDL_user_free(interfaceProperties);
  1390. NmpAcquireLock();
  1391. }
  1392. else {
  1393. ClRtlLogPrint(LOG_CRITICAL,
  1394. "[NM] Failed to marshall properties for interface %1!ws!, status %2!u!\n",
  1395. InterfaceInfo->Id,
  1396. status
  1397. );
  1398. }
  1399. return(status);
  1400. } // NmpGlobalSetInterfaceInfo
  1401. DWORD
  1402. NmpGlobalDeleteInterface(
  1403. IN LPWSTR InterfaceId,
  1404. IN OUT PBOOLEAN NetworkDeleted
  1405. )
  1406. /*++
  1407. Notes:
  1408. Called with the NmpLock held.
  1409. --*/
  1410. {
  1411. DWORD status = ERROR_SUCCESS;
  1412. PNM_INTERFACE netInterface;
  1413. ClRtlLogPrint(LOG_NOISE,
  1414. "[NM] Issuing global update to delete interface %1!ws!.\n",
  1415. InterfaceId
  1416. );
  1417. //
  1418. // Find the interface object
  1419. //
  1420. netInterface = OmReferenceObjectById(ObjectTypeNetInterface, InterfaceId);
  1421. if (netInterface != NULL) {
  1422. NmpReleaseLock();
  1423. //
  1424. // Issue a global update
  1425. //
  1426. status = GumSendUpdateEx(
  1427. GumUpdateMembership,
  1428. NmUpdateDeleteInterface,
  1429. 1,
  1430. (lstrlenW(InterfaceId)+1) * sizeof(WCHAR),
  1431. InterfaceId
  1432. );
  1433. NmpAcquireLock();
  1434. if (status == ERROR_SUCCESS) {
  1435. //
  1436. // Check if the network was deleted too
  1437. //
  1438. if (netInterface->Network->Flags & NM_FLAG_DELETE_PENDING) {
  1439. *NetworkDeleted = TRUE;
  1440. }
  1441. else {
  1442. *NetworkDeleted = FALSE;
  1443. }
  1444. }
  1445. else {
  1446. ClRtlLogPrint(LOG_CRITICAL,
  1447. "[NM] Global update to delete interface %1!ws! failed, status %2!u!.\n",
  1448. InterfaceId,
  1449. status
  1450. );
  1451. }
  1452. OmDereferenceObject(netInterface);
  1453. }
  1454. else {
  1455. ClRtlLogPrint(LOG_CRITICAL,
  1456. "[NM] Unable to find interface %1!ws!.\n",
  1457. InterfaceId
  1458. );
  1459. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  1460. }
  1461. return(status);
  1462. } // NmpGlobalDeleteInterface
  1463. /////////////////////////////////////////////////////////////////////////////
  1464. //
  1465. // Routines called by other cluster service components
  1466. //
  1467. /////////////////////////////////////////////////////////////////////////////
  1468. CLUSTER_NETINTERFACE_STATE
  1469. NmGetInterfaceState(
  1470. IN PNM_INTERFACE Interface
  1471. )
  1472. /*++
  1473. Routine Description:
  1474. Arguments:
  1475. Return Value:
  1476. Notes:
  1477. Because the caller must have a reference on the object and the
  1478. call is so simple, there is no reason to put the call through the
  1479. EnterApi/LeaveApi dance.
  1480. --*/
  1481. {
  1482. CLUSTER_NETINTERFACE_STATE state;
  1483. NmpAcquireLock();
  1484. state = Interface->State;
  1485. NmpReleaseLock();
  1486. return(state);
  1487. } // NmGetInterfaceState
  1488. DWORD
  1489. NmGetInterfaceForNodeAndNetwork(
  1490. IN LPCWSTR NodeName,
  1491. IN LPCWSTR NetworkName,
  1492. OUT LPWSTR * InterfaceName
  1493. )
  1494. /*++
  1495. Routine Description:
  1496. Returns the name of the interface which connects a specified node
  1497. to a specified network.
  1498. Arguments:
  1499. NodeName - A pointer to the unicode name of the node.
  1500. NetworkName - A pointer to the unicode name of the network.
  1501. InterfaceName - On output, contains a pointer to the unicode name of the
  1502. interface.
  1503. Return Value:
  1504. ERROR_SUCCESS if the routine succeeds.
  1505. A Win32 error code otherwise.
  1506. Notes:
  1507. --*/
  1508. {
  1509. DWORD status;
  1510. NmpAcquireLock();
  1511. if (NmpLockedEnterApi(NmStateOnline)) {
  1512. PNM_NODE node = OmReferenceObjectByName(ObjectTypeNode, NodeName);
  1513. if (node != NULL) {
  1514. PNM_NETWORK network = OmReferenceObjectByName(
  1515. ObjectTypeNetwork,
  1516. NetworkName
  1517. );
  1518. if (network != NULL) {
  1519. PLIST_ENTRY entry;
  1520. PNM_INTERFACE netInterface;
  1521. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  1522. for (entry = node->InterfaceList.Flink;
  1523. entry != &(node->InterfaceList);
  1524. entry = entry->Flink
  1525. )
  1526. {
  1527. netInterface = CONTAINING_RECORD(
  1528. entry,
  1529. NM_INTERFACE,
  1530. NodeLinkage
  1531. );
  1532. if (netInterface->Network == network) {
  1533. LPCWSTR interfaceId = OmObjectName(netInterface);
  1534. DWORD nameLength = NM_WCSLEN(interfaceId);
  1535. *InterfaceName = MIDL_user_allocate(nameLength);
  1536. if (*InterfaceName != NULL) {
  1537. lstrcpyW(*InterfaceName, interfaceId);
  1538. status = ERROR_SUCCESS;
  1539. }
  1540. else {
  1541. status = ERROR_NOT_ENOUGH_MEMORY;
  1542. }
  1543. }
  1544. }
  1545. OmDereferenceObject(network);
  1546. }
  1547. else {
  1548. status = ERROR_CLUSTER_NETWORK_NOT_FOUND;
  1549. }
  1550. OmDereferenceObject(node);
  1551. }
  1552. else {
  1553. status = ERROR_CLUSTER_NODE_NOT_FOUND;
  1554. }
  1555. NmpLockedLeaveApi();
  1556. }
  1557. else {
  1558. status = ERROR_NODE_NOT_AVAILABLE;
  1559. ClRtlLogPrint(LOG_NOISE,
  1560. "[NM] Not in valid state to process GetInterfaceForNodeAndNetwork request.\n"
  1561. );
  1562. }
  1563. NmpReleaseLock();
  1564. return(status);
  1565. } // NmGetInterfaceForNodeAndNetwork
  1566. /////////////////////////////////////////////////////////////////////////////
  1567. //
  1568. // Handlers for global updates
  1569. //
  1570. /////////////////////////////////////////////////////////////////////////////
  1571. DWORD
  1572. NmpUpdateCreateInterface(
  1573. IN BOOL IsSourceNode,
  1574. IN PVOID InterfacePropertyList,
  1575. IN LPDWORD InterfacePropertyListSize
  1576. )
  1577. /*++
  1578. Routine Description:
  1579. Global update handler for creating a new interface. The interface
  1580. definition is read from the cluster database, and a corresponding
  1581. object is instantiated. The cluster transport is also updated if
  1582. necessary.
  1583. Arguments:
  1584. IsSourceNode - Set to TRUE if this node is the source of the update.
  1585. Set to FALSE otherwise.
  1586. Return Value:
  1587. ERROR_SUCCESS if the routine succeeds.
  1588. A Win32 error code otherwise.
  1589. Notes:
  1590. This routine must not be called with the NM lock held.
  1591. --*/
  1592. {
  1593. DWORD status = ERROR_SUCCESS;
  1594. NM_INTERFACE_INFO2 interfaceInfo;
  1595. BOOLEAN lockAcquired = FALSE;
  1596. HLOCALXSACTION xaction = NULL;
  1597. PNM_INTERFACE netInterface = NULL;
  1598. if (!NmpEnterApi(NmStateOnline)) {
  1599. ClRtlLogPrint(LOG_NOISE,
  1600. "[NM] Not in valid state to process CreateInterface update.\n"
  1601. );
  1602. return(ERROR_NODE_NOT_AVAILABLE);
  1603. }
  1604. ZeroMemory(&interfaceInfo, sizeof(interfaceInfo));
  1605. //
  1606. // Unmarshall the property list.
  1607. //
  1608. status = NmpConvertPropertyListToInterfaceInfo(
  1609. InterfacePropertyList,
  1610. *InterfacePropertyListSize,
  1611. &interfaceInfo
  1612. );
  1613. if (status == ERROR_SUCCESS) {
  1614. //
  1615. // Fake missing V2 fields
  1616. //
  1617. if (interfaceInfo.AdapterId == NULL) {
  1618. interfaceInfo.AdapterId = NmpUnknownString;
  1619. }
  1620. ClRtlLogPrint(LOG_NOISE,
  1621. "[NM] Received update to create interface %1!ws!.\n",
  1622. interfaceInfo.Id
  1623. );
  1624. //
  1625. // Start a transaction - this must be done before acquiring
  1626. // the NM lock.
  1627. //
  1628. xaction = DmBeginLocalUpdate();
  1629. if (xaction != NULL) {
  1630. NmpAcquireLock(); lockAcquired = TRUE;
  1631. status = NmpCreateInterfaceDefinition(&interfaceInfo, xaction);
  1632. if (status == ERROR_SUCCESS) {
  1633. CL_NODE_ID joinerNodeId;
  1634. joinerNodeId = NmpJoinerNodeId;
  1635. NmpReleaseLock();
  1636. netInterface = NmpCreateInterfaceObject(
  1637. &interfaceInfo,
  1638. TRUE // Do retry on failure
  1639. );
  1640. NmpAcquireLock();
  1641. if (netInterface != NULL) {
  1642. //
  1643. // If a node happens to be joining right now, flag
  1644. // the fact that it is now out of synch with the
  1645. // cluster config.
  1646. //
  1647. if ( ( (joinerNodeId != ClusterInvalidNodeId) &&
  1648. (netInterface->Node->NodeId != joinerNodeId)
  1649. ) ||
  1650. ( (NmpJoinerNodeId != ClusterInvalidNodeId) &&
  1651. (netInterface->Node->NodeId != NmpJoinerNodeId)
  1652. )
  1653. )
  1654. {
  1655. NmpJoinerOutOfSynch = TRUE;
  1656. }
  1657. ClusterEvent(
  1658. CLUSTER_EVENT_NETINTERFACE_ADDED,
  1659. netInterface
  1660. );
  1661. }
  1662. else {
  1663. status = GetLastError();
  1664. ClRtlLogPrint(LOG_CRITICAL,
  1665. "[NM] Failed to create object for interface %1!ws!, "
  1666. "status %2!u!.\n",
  1667. interfaceInfo.Id,
  1668. status
  1669. );
  1670. }
  1671. }
  1672. else {
  1673. ClRtlLogPrint(LOG_CRITICAL,
  1674. "[NM] Failed to write definition for interface %1!ws!, "
  1675. "status %2!u!.\n",
  1676. interfaceInfo.Id,
  1677. status
  1678. );
  1679. }
  1680. }
  1681. else {
  1682. status = GetLastError();
  1683. ClRtlLogPrint(LOG_CRITICAL,
  1684. "[NM] Failed to begin a transaction, status %1!u!\n",
  1685. status
  1686. );
  1687. }
  1688. //
  1689. // Remove faked V2 fields
  1690. //
  1691. if (interfaceInfo.AdapterId == NmpUnknownString) {
  1692. interfaceInfo.AdapterId = NULL;
  1693. }
  1694. ClNetFreeInterfaceInfo(&interfaceInfo);
  1695. }
  1696. else {
  1697. ClRtlLogPrint( LOG_CRITICAL,
  1698. "[NM] Failed to unmarshall properties for new interface, "
  1699. "status %1!u!.\n",
  1700. status
  1701. );
  1702. }
  1703. if (lockAcquired) {
  1704. NmpLockedLeaveApi();
  1705. NmpReleaseLock();
  1706. }
  1707. else {
  1708. NmpLeaveApi();
  1709. }
  1710. if (xaction != NULL) {
  1711. //
  1712. // Complete the transaction - this must be done after releasing
  1713. // the NM lock.
  1714. //
  1715. if (status == ERROR_SUCCESS) {
  1716. DmCommitLocalUpdate(xaction);
  1717. }
  1718. else {
  1719. DmAbortLocalUpdate(xaction);
  1720. }
  1721. }
  1722. if (netInterface != NULL) {
  1723. //
  1724. // Remove the reference put on by
  1725. // NmpCreateInterfaceObject.
  1726. //
  1727. OmDereferenceObject(netInterface);
  1728. }
  1729. return(status);
  1730. } // NmpUpdateCreateInterface
  1731. DWORD
  1732. NmpUpdateSetInterfaceInfo(
  1733. IN BOOL IsSourceNode,
  1734. IN PVOID InterfacePropertyList,
  1735. IN LPDWORD InterfacePropertyListSize
  1736. )
  1737. /*++
  1738. Routine Description:
  1739. Global update handler for setting the properties of an interface.
  1740. This update is issued in response to interface property changes that
  1741. are detected internally.
  1742. Arguments:
  1743. IsSourceNode - Set to TRUE if this node is the source of the update.
  1744. Set to FALSE otherwise.
  1745. InterfacePropertyList - A pointer to a property list that encodes the
  1746. new properties for the interface. All of the
  1747. string properties must be present, except those
  1748. noted in the code below.
  1749. InterfacePropertyListSize - A pointer to a variable containing the size,
  1750. in bytes, of the property list described
  1751. by the InterfacePropertyList parameter.
  1752. Return Value:
  1753. ERROR_SUCCESS if the routine succeeds.
  1754. A Win32 error code otherwise.
  1755. --*/
  1756. {
  1757. DWORD status;
  1758. NM_INTERFACE_INFO2 interfaceInfo;
  1759. if (!NmpEnterApi(NmStateOnline)) {
  1760. ClRtlLogPrint(LOG_NOISE,
  1761. "[NM] Not in valid state to process SetInterfaceInfo update.\n"
  1762. );
  1763. return(ERROR_NODE_NOT_AVAILABLE);
  1764. }
  1765. //
  1766. // Unmarshall the property list so we can extract the interface ID.
  1767. //
  1768. status = NmpConvertPropertyListToInterfaceInfo(
  1769. InterfacePropertyList,
  1770. *InterfacePropertyListSize,
  1771. &interfaceInfo
  1772. );
  1773. if (status == ERROR_SUCCESS) {
  1774. PNM_INTERFACE netInterface;
  1775. ClRtlLogPrint(LOG_NOISE,
  1776. "[NM] Received update to set properties for interface %1!ws!.\n",
  1777. interfaceInfo.Id
  1778. );
  1779. //
  1780. // Fake missing V2 fields
  1781. //
  1782. if (interfaceInfo.AdapterId == NULL) {
  1783. interfaceInfo.AdapterId = NmpUnknownString;
  1784. }
  1785. //
  1786. // Find the interface object
  1787. //
  1788. netInterface = OmReferenceObjectById(
  1789. ObjectTypeNetInterface,
  1790. interfaceInfo.Id
  1791. );
  1792. if (netInterface != NULL) {
  1793. HLOCALXSACTION xaction;
  1794. //
  1795. // Begin a transaction - this must be done before acquiring the
  1796. // NM lock.
  1797. //
  1798. xaction = DmBeginLocalUpdate();
  1799. if (xaction != NULL) {
  1800. NmpAcquireLock();
  1801. //
  1802. // Process the changes
  1803. //
  1804. status = NmpLocalSetInterfaceInfo(
  1805. netInterface,
  1806. &interfaceInfo,
  1807. xaction
  1808. );
  1809. NmpReleaseLock();
  1810. //
  1811. // Complete the transaction - this must be done after
  1812. // releasing the NM lock.
  1813. //
  1814. if (status == ERROR_SUCCESS) {
  1815. DmCommitLocalUpdate(xaction);
  1816. }
  1817. else {
  1818. DmAbortLocalUpdate(xaction);
  1819. }
  1820. }
  1821. else {
  1822. status = GetLastError();
  1823. ClRtlLogPrint(LOG_CRITICAL,
  1824. "[NM] Failed to begin a transaction, status %1!u!\n",
  1825. status
  1826. );
  1827. }
  1828. OmDereferenceObject(netInterface);
  1829. }
  1830. else {
  1831. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  1832. ClRtlLogPrint(LOG_CRITICAL,
  1833. "[NM] Unable to find interface %1!ws!.\n",
  1834. interfaceInfo.Id
  1835. );
  1836. }
  1837. //
  1838. // Remove faked V2 fields
  1839. //
  1840. if (interfaceInfo.AdapterId == NmpUnknownString) {
  1841. interfaceInfo.AdapterId = NULL;
  1842. }
  1843. ClNetFreeInterfaceInfo(&interfaceInfo);
  1844. }
  1845. else {
  1846. ClRtlLogPrint( LOG_CRITICAL,
  1847. "[NM] Failed to unmarshall properties for interface update, "
  1848. "status %1!u!.\n",
  1849. status
  1850. );
  1851. }
  1852. NmpLeaveApi();
  1853. return(status);
  1854. } // NmpUpdateSetInterfaceInfo
  1855. DWORD
  1856. NmpUpdateSetInterfaceCommonProperties(
  1857. IN BOOL IsSourceNode,
  1858. IN LPWSTR InterfaceId,
  1859. IN UCHAR * PropertyList,
  1860. IN LPDWORD PropertyListLength
  1861. )
  1862. /*++
  1863. Routine Description:
  1864. Global update handler for setting the common properties of a interface.
  1865. This update is issued in response to a property change request made
  1866. through the cluster API.
  1867. Arguments:
  1868. IsSourceNode - Set to TRUE if this node is the source of the update.
  1869. Set to FALSE otherwise.
  1870. InterfaceId - A pointer to a unicode string containing the ID of the
  1871. interface to update.
  1872. PropertyList - A pointer to a property list that encodes the
  1873. new properties for the interface. The list might contain
  1874. only a partial property set for the object.
  1875. PropertyListLength - A pointer to a variable containing the size,
  1876. in bytes, of the property list described
  1877. by the PropertyList parameter.
  1878. Return Value:
  1879. ERROR_SUCCESS if the routine succeeds.
  1880. A Win32 error code otherwise.
  1881. --*/
  1882. {
  1883. DWORD status = ERROR_SUCCESS;
  1884. PNM_INTERFACE netInterface;
  1885. if (!NmpEnterApi(NmStateOnline)) {
  1886. ClRtlLogPrint(LOG_NOISE,
  1887. "[NM] Not in valid state to process SetInterfaceCommonProperties "
  1888. "update.\n"
  1889. );
  1890. return(ERROR_NODE_NOT_AVAILABLE);
  1891. }
  1892. ClRtlLogPrint(LOG_NOISE,
  1893. "[NM] Received update to set common properties for "
  1894. "interface %1!ws!.\n",
  1895. InterfaceId
  1896. );
  1897. //
  1898. // Find the interface's object
  1899. //
  1900. netInterface = OmReferenceObjectById(
  1901. ObjectTypeNetInterface,
  1902. InterfaceId
  1903. );
  1904. if (netInterface != NULL) {
  1905. HLOCALXSACTION xaction;
  1906. //
  1907. // Begin a transaction - this must be done before acquiring the
  1908. // NM lock.
  1909. //
  1910. xaction = DmBeginLocalUpdate();
  1911. if (xaction != NULL) {
  1912. NM_INTERFACE_INFO2 interfaceInfo;
  1913. ZeroMemory(&interfaceInfo, sizeof(interfaceInfo));
  1914. NmpAcquireLock();
  1915. //
  1916. // Validate the property list and convert it to an
  1917. // interface info struct. Properties that are not present
  1918. // in the property list will be copied from the interface
  1919. // object.
  1920. //
  1921. status = NmpInterfaceValidateCommonProperties(
  1922. netInterface,
  1923. PropertyList,
  1924. *PropertyListLength,
  1925. &interfaceInfo
  1926. );
  1927. if (status == ERROR_SUCCESS) {
  1928. //
  1929. // Fake missing V2 fields
  1930. //
  1931. if (interfaceInfo.AdapterId == NULL) {
  1932. interfaceInfo.AdapterId = NmpUnknownString;
  1933. }
  1934. //
  1935. // Apply the changes
  1936. //
  1937. status = NmpLocalSetInterfaceInfo(
  1938. netInterface,
  1939. &interfaceInfo,
  1940. xaction
  1941. );
  1942. NmpReleaseLock();
  1943. //
  1944. // Remove faked V2 fields
  1945. //
  1946. if (interfaceInfo.AdapterId == NmpUnknownString) {
  1947. interfaceInfo.AdapterId = NULL;
  1948. }
  1949. ClNetFreeInterfaceInfo(&interfaceInfo);
  1950. }
  1951. else {
  1952. NmpReleaseLock();
  1953. ClRtlLogPrint(LOG_CRITICAL,
  1954. "[NM] Update to set common properties for interface "
  1955. "%1!ws! failed because property list validation failed "
  1956. "with status %2!u!.\n",
  1957. InterfaceId,
  1958. status
  1959. );
  1960. }
  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. else {
  1973. status = GetLastError();
  1974. ClRtlLogPrint(LOG_CRITICAL,
  1975. "[NM] Failed to begin a transaction, status %1!u!\n",
  1976. status
  1977. );
  1978. }
  1979. OmDereferenceObject(netInterface);
  1980. }
  1981. else {
  1982. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  1983. ClRtlLogPrint(LOG_CRITICAL,
  1984. "[NM] Unable to find interface %1!ws!.\n",
  1985. InterfaceId
  1986. );
  1987. }
  1988. NmpLeaveApi();
  1989. return(status);
  1990. } // NmpUpdateSetInterfaceCommonProperties
  1991. DWORD
  1992. NmpUpdateDeleteInterface(
  1993. IN BOOL IsSourceNode,
  1994. IN LPWSTR InterfaceId
  1995. )
  1996. /*++
  1997. Routine Description:
  1998. Global update handler for deleting an interface. The corresponding
  1999. object is deleted. The cluster transport is also updated if
  2000. necessary.
  2001. Arguments:
  2002. IsSourceNode - Set to TRUE if this node is the source of the update.
  2003. Set to FALSE otherwise.
  2004. InterfaceId - A pointer to a unicode string containing the ID of the
  2005. interface to delete.
  2006. Return Value:
  2007. ERROR_SUCCESS if the routine succeeds.
  2008. A Win32 error code otherwise.
  2009. --*/
  2010. {
  2011. DWORD status;
  2012. PNM_INTERFACE netInterface;
  2013. HLOCALXSACTION xaction;
  2014. if (!NmpEnterApi(NmStateOnline)) {
  2015. ClRtlLogPrint(LOG_NOISE,
  2016. "[NM] Not in valid state to process DeleteInterface update.\n"
  2017. );
  2018. return(ERROR_NODE_NOT_AVAILABLE);
  2019. }
  2020. ClRtlLogPrint(LOG_NOISE,
  2021. "[NM] Received update request to delete interface %1!ws!.\n",
  2022. InterfaceId
  2023. );
  2024. xaction = DmBeginLocalUpdate();
  2025. if (xaction != NULL) {
  2026. //
  2027. // Find the interface object
  2028. //
  2029. netInterface = OmReferenceObjectById(
  2030. ObjectTypeNetInterface,
  2031. InterfaceId
  2032. );
  2033. if (netInterface != NULL) {
  2034. BOOLEAN deleteNetwork = FALSE;
  2035. PNM_NETWORK network;
  2036. LPCWSTR networkId;
  2037. NmpAcquireLock();
  2038. network = netInterface->Network;
  2039. networkId = OmObjectId(network);
  2040. //
  2041. // Delete the interface definition from the database.
  2042. //
  2043. status = DmLocalDeleteTree(
  2044. xaction,
  2045. DmNetInterfacesKey,
  2046. InterfaceId
  2047. );
  2048. if (status == ERROR_SUCCESS) {
  2049. if (network->InterfaceCount == 1) {
  2050. //
  2051. // This is the last interface on the network.
  2052. // Delete the network too.
  2053. //
  2054. deleteNetwork = TRUE;
  2055. status = DmLocalDeleteTree(
  2056. xaction,
  2057. DmNetworksKey,
  2058. networkId
  2059. );
  2060. if (status != ERROR_SUCCESS) {
  2061. ClRtlLogPrint(LOG_CRITICAL,
  2062. "[NM] Failed to delete definition for network "
  2063. "%1!ws!, status %2!u!.\n",
  2064. networkId,
  2065. status
  2066. );
  2067. }
  2068. }
  2069. }
  2070. else {
  2071. ClRtlLogPrint(LOG_CRITICAL,
  2072. "[NM] Failed to delete definition for interface %1!ws!, "
  2073. "status %2!u!.\n",
  2074. InterfaceId,
  2075. status
  2076. );
  2077. }
  2078. if (status == ERROR_SUCCESS) {
  2079. NmpDeleteInterfaceObject(netInterface, TRUE);
  2080. if (deleteNetwork) {
  2081. NmpDeleteNetworkObject(network, TRUE);
  2082. }
  2083. else if (NmpIsNetworkRegistered(network)) {
  2084. //
  2085. // Schedule a connectivity report.
  2086. //
  2087. NmpScheduleNetworkConnectivityReport(network);
  2088. }
  2089. //
  2090. // If a node happens to be joining right now, flag the
  2091. // fact that it is now out of synch with the cluster
  2092. // config.
  2093. //
  2094. if ( (NmpJoinerNodeId != ClusterInvalidNodeId) &&
  2095. (netInterface->Node->NodeId != NmpJoinerNodeId)
  2096. )
  2097. {
  2098. NmpJoinerOutOfSynch = TRUE;
  2099. }
  2100. }
  2101. NmpReleaseLock();
  2102. OmDereferenceObject(netInterface);
  2103. }
  2104. else {
  2105. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  2106. ClRtlLogPrint(LOG_UNUSUAL,
  2107. "[NM] Unable to find interface %1!ws!.\n",
  2108. InterfaceId
  2109. );
  2110. }
  2111. //
  2112. // Complete the transaction
  2113. //
  2114. if (status == ERROR_SUCCESS) {
  2115. DmCommitLocalUpdate(xaction);
  2116. }
  2117. else {
  2118. DmAbortLocalUpdate(xaction);
  2119. }
  2120. }
  2121. else {
  2122. status = GetLastError();
  2123. ClRtlLogPrint(LOG_CRITICAL,
  2124. "[NM] Failed to begin a transaction, status %1!u!\n",
  2125. status
  2126. );
  2127. }
  2128. NmpLeaveApi();
  2129. return(status);
  2130. } // NmpUpdateDeleteInterface
  2131. /////////////////////////////////////////////////////////////////////////////
  2132. //
  2133. // Update helper routines
  2134. //
  2135. /////////////////////////////////////////////////////////////////////////////
  2136. DWORD
  2137. NmpLocalSetInterfaceInfo(
  2138. IN PNM_INTERFACE Interface,
  2139. IN PNM_INTERFACE_INFO2 InterfaceInfo,
  2140. IN HLOCALXSACTION Xaction
  2141. )
  2142. /*++
  2143. Routine Description:
  2144. Arguments:
  2145. Return Value:
  2146. ERROR_SUCCESS if the routine succeeds.
  2147. A Win32 error code otherwise.
  2148. Notes:
  2149. Called with the NmpLock held.
  2150. --*/
  2151. {
  2152. DWORD status = ERROR_SUCCESS;
  2153. PNM_NETWORK network = Interface->Network;
  2154. LPCWSTR interfaceId = OmObjectId(Interface);
  2155. HDMKEY interfaceKey = NULL;
  2156. BOOLEAN updateClusnet = FALSE;
  2157. BOOLEAN propertyChanged = FALSE;
  2158. BOOLEAN nameChanged = FALSE;
  2159. LPWSTR descString = NULL;
  2160. LPWSTR adapterNameString = NULL;
  2161. LPWSTR adapterIdString = NULL;
  2162. LPWSTR addressString = NULL;
  2163. LPWSTR endpointString = NULL;
  2164. DWORD size;
  2165. ULONG ifAddress;
  2166. //
  2167. // Open the interface's database key
  2168. //
  2169. interfaceKey = DmOpenKey(DmNetInterfacesKey, interfaceId, KEY_WRITE);
  2170. if (interfaceKey == NULL) {
  2171. status = GetLastError();
  2172. ClRtlLogPrint(LOG_CRITICAL,
  2173. "[NM] Failed to open database key for interface %1!ws!, "
  2174. "status %2!u!\n",
  2175. interfaceId,
  2176. status
  2177. );
  2178. goto error_exit;
  2179. }
  2180. //
  2181. // Check if the description changed.
  2182. //
  2183. if (wcscmp(Interface->Description, InterfaceInfo->Description) != 0) {
  2184. size = NM_WCSLEN(InterfaceInfo->Description);
  2185. //
  2186. // Update the database
  2187. //
  2188. status = DmLocalSetValue(
  2189. Xaction,
  2190. interfaceKey,
  2191. CLUSREG_NAME_NETIFACE_DESC,
  2192. REG_SZ,
  2193. (CONST BYTE *) InterfaceInfo->Description,
  2194. size
  2195. );
  2196. if (status != ERROR_SUCCESS) {
  2197. ClRtlLogPrint(LOG_CRITICAL,
  2198. "[NM] Set of name value failed for interface %1!ws!, "
  2199. "status %2!u!.\n",
  2200. interfaceId,
  2201. status
  2202. );
  2203. goto error_exit;
  2204. }
  2205. //
  2206. // Allocate new memory resources. The object will be updated when the
  2207. // transaction commits.
  2208. //
  2209. descString = MIDL_user_allocate(size);
  2210. if (descString == NULL) {
  2211. status = ERROR_NOT_ENOUGH_MEMORY;
  2212. ClRtlLogPrint(LOG_CRITICAL, "[NM] Failed to allocate memory\n");
  2213. goto error_exit;
  2214. }
  2215. wcscpy(descString, InterfaceInfo->Description);
  2216. propertyChanged = TRUE;
  2217. }
  2218. //
  2219. // Check if the adapter name changed.
  2220. //
  2221. if (wcscmp(Interface->AdapterName, InterfaceInfo->AdapterName) != 0) {
  2222. size = NM_WCSLEN(InterfaceInfo->AdapterName);
  2223. //
  2224. // Update the database
  2225. //
  2226. status = DmLocalSetValue(
  2227. Xaction,
  2228. interfaceKey,
  2229. CLUSREG_NAME_NETIFACE_ADAPTER_NAME,
  2230. REG_SZ,
  2231. (CONST BYTE *) InterfaceInfo->AdapterName,
  2232. size
  2233. );
  2234. if (status != ERROR_SUCCESS) {
  2235. ClRtlLogPrint(LOG_CRITICAL,
  2236. "[NM] Set of adapter name value failed for interface %1!ws!, "
  2237. "status %2!u!.\n",
  2238. interfaceId,
  2239. status
  2240. );
  2241. goto error_exit;
  2242. }
  2243. //
  2244. // Allocate new memory resources. The object will be updated when the
  2245. // transaction commits.
  2246. //
  2247. adapterNameString = MIDL_user_allocate(size);
  2248. if (adapterNameString == NULL) {
  2249. status = ERROR_NOT_ENOUGH_MEMORY;
  2250. ClRtlLogPrint(LOG_CRITICAL, "[NM] Failed to allocate memory\n");
  2251. goto error_exit;
  2252. }
  2253. wcscpy(adapterNameString, InterfaceInfo->AdapterName);
  2254. propertyChanged = TRUE;
  2255. }
  2256. //
  2257. // Check if the adapter Id changed.
  2258. //
  2259. if (wcscmp(Interface->AdapterId, InterfaceInfo->AdapterId) != 0) {
  2260. size = NM_WCSLEN(InterfaceInfo->AdapterId);
  2261. //
  2262. // Update the database
  2263. //
  2264. status = DmLocalSetValue(
  2265. Xaction,
  2266. interfaceKey,
  2267. CLUSREG_NAME_NETIFACE_ADAPTER_ID,
  2268. REG_SZ,
  2269. (CONST BYTE *) InterfaceInfo->AdapterId,
  2270. size
  2271. );
  2272. if (status != ERROR_SUCCESS) {
  2273. ClRtlLogPrint(LOG_CRITICAL,
  2274. "[NM] Set of adapter Id value failed for interface %1!ws!, "
  2275. "status %2!u!.\n",
  2276. interfaceId,
  2277. status
  2278. );
  2279. goto error_exit;
  2280. }
  2281. //
  2282. // Allocate new memory resources. The object will be updated when the
  2283. // transaction commits.
  2284. //
  2285. adapterIdString = MIDL_user_allocate(size);
  2286. if (adapterIdString == NULL) {
  2287. status = ERROR_NOT_ENOUGH_MEMORY;
  2288. ClRtlLogPrint(LOG_CRITICAL, "[NM] Failed to allocate memory\n");
  2289. goto error_exit;
  2290. }
  2291. wcscpy(adapterIdString, InterfaceInfo->AdapterId);
  2292. propertyChanged = TRUE;
  2293. }
  2294. //
  2295. // Check if the address changed.
  2296. //
  2297. if (wcscmp(Interface->Address, InterfaceInfo->Address) != 0) {
  2298. status = ClRtlTcpipStringToAddress(
  2299. InterfaceInfo->Address,
  2300. &ifAddress
  2301. );
  2302. if (status != ERROR_SUCCESS) {
  2303. ClRtlLogPrint(LOG_UNUSUAL,
  2304. "[NM] Failed to convert interface address string %1!ws! to "
  2305. "binary, status %2!u!.\n",
  2306. InterfaceInfo->Address,
  2307. status
  2308. );
  2309. goto error_exit;
  2310. }
  2311. size = NM_WCSLEN(InterfaceInfo->Address);
  2312. //
  2313. // Update the database
  2314. //
  2315. status = DmLocalSetValue(
  2316. Xaction,
  2317. interfaceKey,
  2318. CLUSREG_NAME_NETIFACE_ADDRESS,
  2319. REG_SZ,
  2320. (CONST BYTE *) InterfaceInfo->Address,
  2321. size
  2322. );
  2323. if (status != ERROR_SUCCESS) {
  2324. ClRtlLogPrint(LOG_CRITICAL,
  2325. "[NM] Set of address value failed for interface %1!ws!, "
  2326. "status %2!u!.\n",
  2327. interfaceId,
  2328. status
  2329. );
  2330. goto error_exit;
  2331. }
  2332. //
  2333. // Allocate new memory resources. The object will be updated when the
  2334. // transaction commits.
  2335. //
  2336. addressString = MIDL_user_allocate(size);
  2337. if (addressString == NULL) {
  2338. status = ERROR_NOT_ENOUGH_MEMORY;
  2339. ClRtlLogPrint(LOG_CRITICAL, "[NM] Failed to allocate memory\n");
  2340. goto error_exit;
  2341. }
  2342. wcscpy(addressString, InterfaceInfo->Address);
  2343. updateClusnet = TRUE;
  2344. propertyChanged = TRUE;
  2345. }
  2346. //
  2347. // Check if the clusnet endpoint changed.
  2348. //
  2349. if (wcscmp(
  2350. Interface->ClusnetEndpoint,
  2351. InterfaceInfo->ClusnetEndpoint
  2352. ) != 0
  2353. )
  2354. {
  2355. size = NM_WCSLEN(InterfaceInfo->ClusnetEndpoint);
  2356. //
  2357. // Update the database
  2358. //
  2359. status = DmLocalSetValue(
  2360. Xaction,
  2361. interfaceKey,
  2362. CLUSREG_NAME_NETIFACE_ENDPOINT,
  2363. REG_SZ,
  2364. (CONST BYTE *) InterfaceInfo->ClusnetEndpoint,
  2365. size
  2366. );
  2367. if (status != ERROR_SUCCESS) {
  2368. ClRtlLogPrint(LOG_CRITICAL,
  2369. "[NM] Set of endpoint value failed for interface %1!ws!, "
  2370. "status %2!u!.\n",
  2371. interfaceId,
  2372. status
  2373. );
  2374. goto error_exit;
  2375. }
  2376. //
  2377. // Allocate new memory resources. The object will be updated when the
  2378. // transaction commits.
  2379. //
  2380. endpointString = MIDL_user_allocate(size);
  2381. if (endpointString == NULL) {
  2382. status = ERROR_NOT_ENOUGH_MEMORY;
  2383. ClRtlLogPrint(LOG_CRITICAL, "[NM] Failed to allocate memory\n");
  2384. goto error_exit;
  2385. }
  2386. wcscpy(endpointString, InterfaceInfo->ClusnetEndpoint);
  2387. updateClusnet = TRUE;
  2388. propertyChanged = TRUE;
  2389. }
  2390. //
  2391. // Check if the object name changed.
  2392. //
  2393. if (wcscmp(OmObjectName(Interface), InterfaceInfo->Name) != 0) {
  2394. size = NM_WCSLEN(InterfaceInfo->Name);
  2395. //
  2396. // Update the database
  2397. //
  2398. status = DmLocalSetValue(
  2399. Xaction,
  2400. interfaceKey,
  2401. CLUSREG_NAME_NETIFACE_NAME,
  2402. REG_SZ,
  2403. (CONST BYTE *) InterfaceInfo->Name,
  2404. size
  2405. );
  2406. if (status != ERROR_SUCCESS) {
  2407. ClRtlLogPrint(LOG_CRITICAL,
  2408. "[NM] Set of name value failed for interface %1!ws!, "
  2409. "status %2!u!.\n",
  2410. interfaceId,
  2411. status
  2412. );
  2413. goto error_exit;
  2414. }
  2415. nameChanged = TRUE;
  2416. propertyChanged = TRUE;
  2417. }
  2418. #ifdef CLUSTER_TESTPOINT
  2419. TESTPT(TpFailNmSetInterfaceInfoAbort) {
  2420. status = 999999;
  2421. goto error_exit;
  2422. }
  2423. #endif
  2424. //
  2425. // Commit the changes
  2426. //
  2427. if (nameChanged) {
  2428. status = OmSetObjectName(Interface, InterfaceInfo->Name);
  2429. if (status != ERROR_SUCCESS) {
  2430. ClRtlLogPrint(LOG_CRITICAL,
  2431. "[NM] Failed to change name for interface %1!ws!, "
  2432. "status %2!u!\n",
  2433. interfaceId,
  2434. status
  2435. );
  2436. goto error_exit;
  2437. }
  2438. }
  2439. if (descString != NULL) {
  2440. MIDL_user_free(Interface->Description);
  2441. Interface->Description = descString;
  2442. }
  2443. if (adapterNameString != NULL) {
  2444. MIDL_user_free(Interface->AdapterName);
  2445. Interface->AdapterName = adapterNameString;
  2446. }
  2447. if (adapterIdString != NULL) {
  2448. MIDL_user_free(Interface->AdapterId);
  2449. Interface->AdapterId = adapterIdString;
  2450. }
  2451. if (addressString != NULL) {
  2452. MIDL_user_free(Interface->Address);
  2453. Interface->Address = addressString;
  2454. Interface->BinaryAddress = ifAddress;
  2455. }
  2456. if (endpointString != NULL) {
  2457. MIDL_user_free(Interface->ClusnetEndpoint);
  2458. Interface->ClusnetEndpoint = endpointString;
  2459. }
  2460. if (interfaceKey != NULL) {
  2461. DmCloseKey(interfaceKey);
  2462. interfaceKey = NULL;
  2463. }
  2464. //
  2465. // Update the cluster transport if this network is active and the local
  2466. // node is attached to it.
  2467. //
  2468. // This operation is not reversible. Failure is fatal for this node.
  2469. //
  2470. network = Interface->Network;
  2471. if (updateClusnet && NmpIsNetworkRegistered(network)) {
  2472. PNM_NODE node = Interface->Node;
  2473. LPCWSTR networkId = OmObjectId(network);
  2474. if (Interface == network->LocalInterface) {
  2475. //
  2476. // This is the local node's interface to the network.
  2477. // We must deregister and then re-register the entire network.
  2478. //
  2479. NmpDeregisterNetwork(network);
  2480. status = NmpRegisterNetwork(
  2481. network,
  2482. TRUE // Do retry on failure
  2483. );
  2484. }
  2485. else {
  2486. //
  2487. // This is another node's interface to the network.
  2488. // Deregister and then re-register the interface.
  2489. //
  2490. NmpDeregisterInterface(Interface);
  2491. status = NmpRegisterInterface(
  2492. Interface,
  2493. TRUE // Do retry on failure
  2494. );
  2495. }
  2496. #ifdef CLUSTER_TESTPOINT
  2497. TESTPT(TpFailNmSetInterfaceInfoHalt) {
  2498. status = 999999;
  2499. }
  2500. #endif
  2501. if (status != ERROR_SUCCESS) {
  2502. //
  2503. // This is fatal.
  2504. //
  2505. CsInconsistencyHalt(status);
  2506. }
  2507. }
  2508. if (propertyChanged) {
  2509. ClusterEvent(CLUSTER_EVENT_NETINTERFACE_PROPERTY_CHANGE, Interface);
  2510. //
  2511. // If a node happens to be joining right now, flag the fact
  2512. // that it is now out of synch with the cluster config.
  2513. //
  2514. if ( (NmpJoinerNodeId != ClusterInvalidNodeId) &&
  2515. (Interface->Node->NodeId != NmpJoinerNodeId)
  2516. )
  2517. {
  2518. NmpJoinerOutOfSynch = TRUE;
  2519. }
  2520. }
  2521. return(ERROR_SUCCESS);
  2522. error_exit:
  2523. if (descString != NULL) {
  2524. MIDL_user_free(descString);
  2525. }
  2526. if (adapterNameString != NULL) {
  2527. MIDL_user_free(adapterNameString);
  2528. }
  2529. if (adapterIdString != NULL) {
  2530. MIDL_user_free(adapterIdString);
  2531. }
  2532. if (addressString != NULL) {
  2533. MIDL_user_free(addressString);
  2534. }
  2535. if (endpointString != NULL) {
  2536. MIDL_user_free(endpointString);
  2537. }
  2538. if (interfaceKey != NULL) {
  2539. DmCloseKey(interfaceKey);
  2540. }
  2541. return(status);
  2542. } // NmpLocalSetInterfaceInfo
  2543. /////////////////////////////////////////////////////////////////////////////
  2544. //
  2545. // Database management routines
  2546. //
  2547. /////////////////////////////////////////////////////////////////////////////
  2548. DWORD
  2549. NmpCreateInterfaceDefinition(
  2550. IN PNM_INTERFACE_INFO2 InterfaceInfo,
  2551. IN HLOCALXSACTION Xaction
  2552. )
  2553. /*++
  2554. Routine Description:
  2555. Creates a new network interface definition in the cluster database.
  2556. Arguments:
  2557. InterfaceInfo - A structure containing the interface's definition.
  2558. Return Value:
  2559. ERROR_SUCCESS if the routine succeeds.
  2560. A Win32 error code otherwise.
  2561. --*/
  2562. {
  2563. DWORD status;
  2564. HDMKEY interfaceKey = NULL;
  2565. DWORD valueLength;
  2566. DWORD disposition;
  2567. ClRtlLogPrint(LOG_NOISE,
  2568. "[NM] Creating database entry for interface %1!ws!\n",
  2569. InterfaceInfo->Id
  2570. );
  2571. CL_ASSERT(InterfaceInfo->Id != NULL);
  2572. interfaceKey = DmLocalCreateKey(
  2573. Xaction,
  2574. DmNetInterfacesKey,
  2575. InterfaceInfo->Id,
  2576. 0,
  2577. KEY_WRITE,
  2578. NULL,
  2579. &disposition
  2580. );
  2581. if (interfaceKey == NULL) {
  2582. status = GetLastError();
  2583. ClRtlLogPrint(LOG_CRITICAL,
  2584. "[NM] Failed to create key for interface %1!ws!, status %2!u!\n",
  2585. InterfaceInfo->Id,
  2586. status
  2587. );
  2588. return(status);
  2589. }
  2590. CL_ASSERT(disposition == REG_CREATED_NEW_KEY);
  2591. //
  2592. // Write the network ID value for this interface.
  2593. //
  2594. valueLength = NM_WCSLEN(InterfaceInfo->NetworkId);
  2595. status = DmLocalSetValue(
  2596. Xaction,
  2597. interfaceKey,
  2598. CLUSREG_NAME_NETIFACE_NETWORK,
  2599. REG_SZ,
  2600. (CONST BYTE *) InterfaceInfo->NetworkId,
  2601. valueLength
  2602. );
  2603. if (status != ERROR_SUCCESS) {
  2604. ClRtlLogPrint(LOG_CRITICAL,
  2605. "[NM] Write of interface network ID failed, status %1!u!.\n",
  2606. status
  2607. );
  2608. goto error_exit;
  2609. }
  2610. //
  2611. // Write the node ID value for this interface.
  2612. //
  2613. valueLength = NM_WCSLEN(InterfaceInfo->NodeId);
  2614. status = DmLocalSetValue(
  2615. Xaction,
  2616. interfaceKey,
  2617. CLUSREG_NAME_NETIFACE_NODE,
  2618. REG_SZ,
  2619. (CONST BYTE *) InterfaceInfo->NodeId,
  2620. valueLength
  2621. );
  2622. if (status != ERROR_SUCCESS) {
  2623. ClRtlLogPrint(LOG_CRITICAL,
  2624. "[NM] Write of interface node ID failed, status %1!u!.\n",
  2625. status
  2626. );
  2627. goto error_exit;
  2628. }
  2629. //
  2630. // Write the rest of the parameters
  2631. //
  2632. status = NmpSetInterfaceDefinition(InterfaceInfo, Xaction);
  2633. if (status != ERROR_SUCCESS) {
  2634. ClRtlLogPrint(LOG_CRITICAL,
  2635. "[NM] Failed to set database definition for interface %1!ws!, status %2!u!.\n",
  2636. InterfaceInfo->Id,
  2637. status
  2638. );
  2639. }
  2640. error_exit:
  2641. if (interfaceKey != NULL) {
  2642. DmCloseKey(interfaceKey);
  2643. }
  2644. return(status);
  2645. } // NmpCreateInterfaceDefinition
  2646. DWORD
  2647. NmpGetInterfaceDefinition(
  2648. IN LPWSTR InterfaceId,
  2649. OUT PNM_INTERFACE_INFO2 InterfaceInfo
  2650. )
  2651. /*++
  2652. Routine Description:
  2653. Reads information about a defined cluster network interface from the
  2654. cluster database and fills in a structure describing it.
  2655. Arguments:
  2656. InterfaceId - A pointer to a unicode string containing the ID of the
  2657. interface to query.
  2658. InterfaceInfo - A pointer to the structure to fill in with node
  2659. information. The ID, NetworkId, and NodeId fields of the
  2660. structure must already be filled in.
  2661. Return Value:
  2662. ERROR_SUCCESS if the routine succeeds.
  2663. A Win32 error code otherwise.
  2664. --*/
  2665. {
  2666. DWORD status;
  2667. HDMKEY interfaceKey = NULL;
  2668. DWORD valueLength, valueSize;
  2669. CL_ASSERT(InterfaceId != NULL);
  2670. ZeroMemory(InterfaceInfo, sizeof(NM_INTERFACE_INFO2));
  2671. interfaceKey = DmOpenKey(DmNetInterfacesKey, InterfaceId, KEY_READ);
  2672. if (interfaceKey == NULL) {
  2673. status = GetLastError();
  2674. ClRtlLogPrint(LOG_CRITICAL,
  2675. "[NM] Failed to open key for interface %1!ws!, status %2!u!\n",
  2676. InterfaceId,
  2677. status
  2678. );
  2679. return(status);
  2680. }
  2681. //
  2682. // Copy the ID string
  2683. //
  2684. InterfaceInfo->Id = MIDL_user_allocate(NM_WCSLEN(InterfaceId));
  2685. if (InterfaceInfo->Id == NULL) {
  2686. status = ERROR_NOT_ENOUGH_MEMORY;
  2687. ClRtlLogPrint(LOG_CRITICAL,
  2688. "[NM] Failed to allocate memory for interface %1!ws!.\n",
  2689. InterfaceId
  2690. );
  2691. goto error_exit;
  2692. }
  2693. wcscpy(InterfaceInfo->Id, InterfaceId);
  2694. //
  2695. // Read the Name for this interface.
  2696. //
  2697. valueLength = 0;
  2698. status = NmpQueryString(
  2699. interfaceKey,
  2700. CLUSREG_NAME_NETIFACE_NAME,
  2701. REG_SZ,
  2702. &(InterfaceInfo->Name),
  2703. &valueLength,
  2704. &valueSize
  2705. );
  2706. if (status != ERROR_SUCCESS) {
  2707. ClRtlLogPrint(LOG_CRITICAL,
  2708. "[NM] Query of network interface name failed, status %1!u!.\n",
  2709. status
  2710. );
  2711. goto error_exit;
  2712. }
  2713. //
  2714. // Read the Description for this interface.
  2715. //
  2716. valueLength = 0;
  2717. status = NmpQueryString(
  2718. interfaceKey,
  2719. CLUSREG_NAME_NETIFACE_DESC,
  2720. REG_SZ,
  2721. &(InterfaceInfo->Description),
  2722. &valueLength,
  2723. &valueSize
  2724. );
  2725. if (status != ERROR_SUCCESS) {
  2726. ClRtlLogPrint(LOG_CRITICAL,
  2727. "[NM] Query of network interface description failed, status %1!u!.\n",
  2728. status
  2729. );
  2730. goto error_exit;
  2731. }
  2732. //
  2733. // Read the Network ID for this interface.
  2734. //
  2735. valueLength = 0;
  2736. status = NmpQueryString(
  2737. interfaceKey,
  2738. CLUSREG_NAME_NETIFACE_NETWORK,
  2739. REG_SZ,
  2740. &(InterfaceInfo->NetworkId),
  2741. &valueLength,
  2742. &valueSize
  2743. );
  2744. if (status != ERROR_SUCCESS) {
  2745. ClRtlLogPrint(LOG_CRITICAL,
  2746. "[NM] Query of network id for interface %1!ws! failed, status %2!u!.\n",
  2747. InterfaceId,
  2748. status
  2749. );
  2750. goto error_exit;
  2751. }
  2752. //
  2753. // Read the Node ID for this interface.
  2754. //
  2755. valueLength = 0;
  2756. status = NmpQueryString(
  2757. interfaceKey,
  2758. CLUSREG_NAME_NETIFACE_NODE,
  2759. REG_SZ,
  2760. &(InterfaceInfo->NodeId),
  2761. &valueLength,
  2762. &valueSize
  2763. );
  2764. if (status != ERROR_SUCCESS) {
  2765. ClRtlLogPrint(LOG_CRITICAL,
  2766. "[NM] Query of node Id for interface %1!ws! failed, status %2!u!.\n",
  2767. InterfaceId,
  2768. status
  2769. );
  2770. goto error_exit;
  2771. }
  2772. //
  2773. // Read the adapter name value for this interface.
  2774. //
  2775. valueLength = 0;
  2776. status = NmpQueryString(
  2777. interfaceKey,
  2778. CLUSREG_NAME_NETIFACE_ADAPTER_NAME,
  2779. REG_SZ,
  2780. &(InterfaceInfo->AdapterName),
  2781. &valueLength,
  2782. &valueSize
  2783. );
  2784. if (status != ERROR_SUCCESS) {
  2785. ClRtlLogPrint(LOG_CRITICAL,
  2786. "[NM] Query of network interface adapter name failed, status %1!u!.\n",
  2787. status
  2788. );
  2789. goto error_exit;
  2790. }
  2791. //
  2792. // Read the adapter Id value for this interface.
  2793. //
  2794. valueLength = 0;
  2795. status = NmpQueryString(
  2796. interfaceKey,
  2797. CLUSREG_NAME_NETIFACE_ADAPTER_ID,
  2798. REG_SZ,
  2799. &(InterfaceInfo->AdapterId),
  2800. &valueLength,
  2801. &valueSize
  2802. );
  2803. if (status != ERROR_SUCCESS) {
  2804. ClRtlLogPrint(LOG_UNUSUAL,
  2805. "[NM] Query of network interface adapter Id failed, status %1!u!.\n",
  2806. status
  2807. );
  2808. InterfaceInfo->AdapterId = midl_user_allocate(
  2809. NM_WCSLEN(NmpUnknownString)
  2810. );
  2811. if (InterfaceInfo->AdapterId == NULL) {
  2812. ClRtlLogPrint(LOG_CRITICAL,
  2813. "[NM] Failed to allocate memory for adapter Id.\n"
  2814. );
  2815. status = ERROR_NOT_ENOUGH_MEMORY;
  2816. goto error_exit;
  2817. }
  2818. lstrcpyW(InterfaceInfo->AdapterId, NmpUnknownString);
  2819. }
  2820. //
  2821. // Read the address value for this interface.
  2822. //
  2823. valueLength = 0;
  2824. status = NmpQueryString(
  2825. interfaceKey,
  2826. CLUSREG_NAME_NETIFACE_ADDRESS,
  2827. REG_SZ,
  2828. &(InterfaceInfo->Address),
  2829. &valueLength,
  2830. &valueSize
  2831. );
  2832. if (status != ERROR_SUCCESS) {
  2833. ClRtlLogPrint(LOG_UNUSUAL,
  2834. "[NM] Query of network interface address failed, status %1!u!.\n",
  2835. status
  2836. );
  2837. goto error_exit;
  2838. }
  2839. //
  2840. // Read the ClusNet endpoint value for this interface.
  2841. //
  2842. valueLength = 0;
  2843. status = NmpQueryString(
  2844. interfaceKey,
  2845. CLUSREG_NAME_NETIFACE_ENDPOINT,
  2846. REG_SZ,
  2847. &(InterfaceInfo->ClusnetEndpoint),
  2848. &valueLength,
  2849. &valueSize
  2850. );
  2851. if (status != ERROR_SUCCESS) {
  2852. ClRtlLogPrint(LOG_UNUSUAL,
  2853. "[NM] Query of ClusNet endpoint value for network interface failed, status %1!u!.\n",
  2854. status
  2855. );
  2856. goto error_exit;
  2857. }
  2858. InterfaceInfo->State = ClusterNetInterfaceUnavailable;
  2859. InterfaceInfo->NetIndex = NmInvalidInterfaceNetIndex;
  2860. CL_ASSERT(status == ERROR_SUCCESS);
  2861. error_exit:
  2862. if (status != ERROR_SUCCESS) {
  2863. ClNetFreeInterfaceInfo(InterfaceInfo);
  2864. }
  2865. if (interfaceKey != NULL) {
  2866. DmCloseKey(interfaceKey);
  2867. }
  2868. return(status);
  2869. } // NmpGetInterfaceDefinition
  2870. DWORD
  2871. NmpSetInterfaceDefinition(
  2872. IN PNM_INTERFACE_INFO2 InterfaceInfo,
  2873. IN HLOCALXSACTION Xaction
  2874. )
  2875. /*++
  2876. Routine Description:
  2877. Updates information for a network interface in the cluster database.
  2878. Arguments:
  2879. InterfaceInfo - A pointer to a structure containing the
  2880. interface's definition.
  2881. Return Value:
  2882. ERROR_SUCCESS if the routine succeeds.
  2883. A Win32 error code otherwise.
  2884. --*/
  2885. {
  2886. DWORD status;
  2887. HDMKEY interfaceKey = NULL;
  2888. DWORD valueLength;
  2889. CL_ASSERT(InterfaceInfo->Id != NULL);
  2890. ClRtlLogPrint(LOG_NOISE,
  2891. "[NM] Setting database entry for interface %1!ws!\n",
  2892. InterfaceInfo->Id
  2893. );
  2894. interfaceKey = DmOpenKey(
  2895. DmNetInterfacesKey,
  2896. InterfaceInfo->Id,
  2897. KEY_WRITE
  2898. );
  2899. if (interfaceKey == NULL) {
  2900. status = GetLastError();
  2901. ClRtlLogPrint(LOG_CRITICAL,
  2902. "[NM] Failed to open key for interface %1!ws!, status %2!u!\n",
  2903. InterfaceInfo->Id,
  2904. status
  2905. );
  2906. return(status);
  2907. }
  2908. //
  2909. // Write the name value for this interface.
  2910. //
  2911. valueLength = (wcslen(InterfaceInfo->Name) + 1) * sizeof(WCHAR);
  2912. status = DmLocalSetValue(
  2913. Xaction,
  2914. interfaceKey,
  2915. CLUSREG_NAME_NETIFACE_NAME,
  2916. REG_SZ,
  2917. (CONST BYTE *) InterfaceInfo->Name,
  2918. valueLength
  2919. );
  2920. if (status != ERROR_SUCCESS) {
  2921. ClRtlLogPrint(LOG_CRITICAL,
  2922. "[NM] Update of interface name failed, status %1!u!.\n",
  2923. status
  2924. );
  2925. goto error_exit;
  2926. }
  2927. //
  2928. // Write the description value for this interface.
  2929. //
  2930. valueLength = (wcslen(InterfaceInfo->Description) + 1) * sizeof(WCHAR);
  2931. status = DmLocalSetValue(
  2932. Xaction,
  2933. interfaceKey,
  2934. CLUSREG_NAME_NETIFACE_DESC,
  2935. REG_SZ,
  2936. (CONST BYTE *) InterfaceInfo->Description,
  2937. valueLength
  2938. );
  2939. if (status != ERROR_SUCCESS) {
  2940. ClRtlLogPrint(LOG_CRITICAL,
  2941. "[NM] Update of interface description failed, status %1!u!.\n",
  2942. status
  2943. );
  2944. goto error_exit;
  2945. }
  2946. //
  2947. // Write the adapter name value for this interface.
  2948. //
  2949. valueLength = (wcslen(InterfaceInfo->AdapterName) + 1) * sizeof(WCHAR);
  2950. status = DmLocalSetValue(
  2951. Xaction,
  2952. interfaceKey,
  2953. CLUSREG_NAME_NETIFACE_ADAPTER_NAME,
  2954. REG_SZ,
  2955. (CONST BYTE *) InterfaceInfo->AdapterName,
  2956. valueLength
  2957. );
  2958. if (status != ERROR_SUCCESS) {
  2959. ClRtlLogPrint(LOG_CRITICAL,
  2960. "[NM] Update of interface adapter name failed, status %1!u!.\n",
  2961. status
  2962. );
  2963. goto error_exit;
  2964. }
  2965. //
  2966. // Write the adapter Id value for this interface.
  2967. //
  2968. valueLength = (wcslen(InterfaceInfo->AdapterId) + 1) * sizeof(WCHAR);
  2969. status = DmLocalSetValue(
  2970. Xaction,
  2971. interfaceKey,
  2972. CLUSREG_NAME_NETIFACE_ADAPTER_ID,
  2973. REG_SZ,
  2974. (CONST BYTE *) InterfaceInfo->AdapterId,
  2975. valueLength
  2976. );
  2977. if (status != ERROR_SUCCESS) {
  2978. ClRtlLogPrint(LOG_CRITICAL,
  2979. "[NM] Update of interface adapter Id failed, status %1!u!.\n",
  2980. status
  2981. );
  2982. goto error_exit;
  2983. }
  2984. //
  2985. // Write the address value for this interface.
  2986. //
  2987. valueLength = (wcslen(InterfaceInfo->Address) + 1) * sizeof(WCHAR);
  2988. status = DmLocalSetValue(
  2989. Xaction,
  2990. interfaceKey,
  2991. CLUSREG_NAME_NETIFACE_ADDRESS,
  2992. REG_SZ,
  2993. (CONST BYTE *) InterfaceInfo->Address,
  2994. valueLength
  2995. );
  2996. if (status != ERROR_SUCCESS) {
  2997. ClRtlLogPrint(LOG_CRITICAL,
  2998. "[NM] Update of interface address failed, status %1!u!.\n",
  2999. status
  3000. );
  3001. goto error_exit;
  3002. }
  3003. //
  3004. // Write the ClusNet endpoint value for this interface.
  3005. //
  3006. valueLength = (wcslen(InterfaceInfo->ClusnetEndpoint) + 1) * sizeof(WCHAR);
  3007. status = DmLocalSetValue(
  3008. Xaction,
  3009. interfaceKey,
  3010. CLUSREG_NAME_NETIFACE_ENDPOINT,
  3011. REG_SZ,
  3012. (CONST BYTE *) InterfaceInfo->ClusnetEndpoint,
  3013. valueLength
  3014. );
  3015. if (status != ERROR_SUCCESS) {
  3016. ClRtlLogPrint(LOG_CRITICAL,
  3017. "[NM] Update of interface endpoint name failed, status %1!u!.\n",
  3018. status
  3019. );
  3020. goto error_exit;
  3021. }
  3022. CL_ASSERT(status == ERROR_SUCCESS);
  3023. error_exit:
  3024. if (interfaceKey != NULL) {
  3025. DmCloseKey(interfaceKey);
  3026. }
  3027. return(status);
  3028. } // NmpSetInterfaceDefinition
  3029. DWORD
  3030. NmpEnumInterfaceDefinitions(
  3031. OUT PNM_INTERFACE_ENUM2 * InterfaceEnum
  3032. )
  3033. /*++
  3034. Routine Description:
  3035. Reads interface information from the cluster database and
  3036. fills in an enumeration structure.
  3037. Arguments:
  3038. InterfaceEnum - A pointer to the variable into which to place a
  3039. pointer to the allocated interface enumeration.
  3040. Return Value:
  3041. ERROR_SUCCESS if the routine succeeds.
  3042. A Win32 error code otherwise.
  3043. --*/
  3044. {
  3045. DWORD status;
  3046. PNM_INTERFACE_ENUM2 interfaceEnum = NULL;
  3047. PNM_INTERFACE_INFO2 interfaceInfo;
  3048. WCHAR interfaceId[CS_NETINTERFACE_ID_LENGTH + 1];
  3049. DWORD i;
  3050. DWORD valueLength;
  3051. DWORD numInterfaces;
  3052. DWORD ignored;
  3053. FILETIME fileTime;
  3054. *InterfaceEnum = NULL;
  3055. //
  3056. // First count the number of interfaces.
  3057. //
  3058. status = DmQueryInfoKey(
  3059. DmNetInterfacesKey,
  3060. &numInterfaces,
  3061. &ignored, // MaxSubKeyLen
  3062. &ignored, // Values
  3063. &ignored, // MaxValueNameLen
  3064. &ignored, // MaxValueLen
  3065. &ignored, // lpcbSecurityDescriptor
  3066. &fileTime
  3067. );
  3068. if (status != ERROR_SUCCESS) {
  3069. ClRtlLogPrint(LOG_CRITICAL,
  3070. "[NM] Failed to query NetworkInterfaces key information, status %1!u!\n",
  3071. status
  3072. );
  3073. return(status);
  3074. }
  3075. if (numInterfaces == 0) {
  3076. valueLength = sizeof(NM_INTERFACE_ENUM2);
  3077. }
  3078. else {
  3079. valueLength = sizeof(NM_INTERFACE_ENUM2) +
  3080. (sizeof(NM_INTERFACE_INFO2) * (numInterfaces-1));
  3081. }
  3082. valueLength = sizeof(NM_INTERFACE_ENUM2) +
  3083. (sizeof(NM_INTERFACE_INFO2) * (numInterfaces-1));
  3084. interfaceEnum = MIDL_user_allocate(valueLength);
  3085. if (interfaceEnum == NULL) {
  3086. ClRtlLogPrint(LOG_CRITICAL, "[NM] Failed to allocate memory.\n");
  3087. return(ERROR_NOT_ENOUGH_MEMORY);
  3088. }
  3089. ZeroMemory(interfaceEnum, valueLength);
  3090. for (i=0; i < numInterfaces; i++) {
  3091. interfaceInfo = &(interfaceEnum->InterfaceList[i]);
  3092. valueLength = sizeof(interfaceId);
  3093. status = DmEnumKey(
  3094. DmNetInterfacesKey,
  3095. i,
  3096. &(interfaceId[0]),
  3097. &valueLength,
  3098. NULL
  3099. );
  3100. if (status != ERROR_SUCCESS) {
  3101. ClRtlLogPrint(LOG_CRITICAL,
  3102. "[NM] Failed to enumerate interface key, status %1!u!\n",
  3103. status
  3104. );
  3105. goto error_exit;
  3106. }
  3107. status = NmpGetInterfaceDefinition(interfaceId, interfaceInfo);
  3108. if (status != ERROR_SUCCESS) {
  3109. goto error_exit;
  3110. }
  3111. interfaceEnum->InterfaceCount++;
  3112. }
  3113. *InterfaceEnum = interfaceEnum;
  3114. return(ERROR_SUCCESS);
  3115. error_exit:
  3116. if (interfaceEnum != NULL) {
  3117. ClNetFreeInterfaceEnum(interfaceEnum);
  3118. }
  3119. return(status);
  3120. } // NmpEnumInterfaceDefinitions
  3121. /////////////////////////////////////////////////////////////////////////////
  3122. //
  3123. // Object management routines
  3124. //
  3125. /////////////////////////////////////////////////////////////////////////////
  3126. DWORD
  3127. NmpCreateInterfaceObjects(
  3128. IN PNM_INTERFACE_ENUM2 InterfaceEnum
  3129. )
  3130. /*++
  3131. Routine Description:
  3132. Processes an interface enumeration and creates interface objects.
  3133. Arguments:
  3134. InterfaceEnum - A pointer to an interface enumeration structure.
  3135. Return Value:
  3136. ERROR_SUCCESS if the routine completes successfully.
  3137. A Win32 error code otherwise.
  3138. --*/
  3139. {
  3140. DWORD status = ERROR_SUCCESS;
  3141. PNM_INTERFACE_INFO2 interfaceInfo;
  3142. PNM_INTERFACE netInterface;
  3143. DWORD i;
  3144. for (i=0; i < InterfaceEnum->InterfaceCount; i++) {
  3145. interfaceInfo = &(InterfaceEnum->InterfaceList[i]);
  3146. netInterface = NmpCreateInterfaceObject(
  3147. interfaceInfo,
  3148. FALSE // Don't retry on failure
  3149. );
  3150. if (netInterface == NULL) {
  3151. status = GetLastError();
  3152. ClRtlLogPrint(LOG_CRITICAL,
  3153. "[NM] Failed to create interface %1!ws!, status %2!u!.\n",
  3154. interfaceInfo->Id,
  3155. status
  3156. );
  3157. break;
  3158. }
  3159. else {
  3160. OmDereferenceObject(netInterface);
  3161. }
  3162. }
  3163. return(status);
  3164. } // NmpCreateInterfaceObjects
  3165. PNM_INTERFACE
  3166. NmpCreateInterfaceObject(
  3167. IN PNM_INTERFACE_INFO2 InterfaceInfo,
  3168. IN BOOLEAN RetryOnFailure
  3169. )
  3170. /*++
  3171. Routine Description:
  3172. Creates an interface object.
  3173. Arguments:
  3174. InterfacInfo - A pointer to a structure containing the definition for
  3175. the interface to create.
  3176. RegisterWithClusterTransport - TRUE if this interface should be registered
  3177. with the cluster transport.
  3178. FALSE otherwise.
  3179. IssueEvent - TRUE if an INTERFACE_ADDED event should be issued when this
  3180. object is created. FALSE otherwise.
  3181. Return Value:
  3182. A pointer to the new interface object on success.
  3183. NULL on failure.
  3184. --*/
  3185. {
  3186. DWORD status;
  3187. PNM_NETWORK network = NULL;
  3188. PNM_NODE node = NULL;
  3189. PNM_INTERFACE netInterface = NULL;
  3190. BOOL created = FALSE;
  3191. PNM_CONNECTIVITY_MATRIX matrixEntry;
  3192. ClRtlLogPrint(LOG_NOISE,
  3193. "[NM] Creating object for interface %1!ws! (%2!ws!).\n",
  3194. InterfaceInfo->Id,
  3195. InterfaceInfo->Name
  3196. );
  3197. status = NmpPrepareToCreateInterface(
  3198. InterfaceInfo,
  3199. &network,
  3200. &node
  3201. );
  3202. if (status != ERROR_SUCCESS) {
  3203. SetLastError(status);
  3204. return(NULL);
  3205. }
  3206. //
  3207. // Create the interface object.
  3208. //
  3209. netInterface = OmCreateObject(
  3210. ObjectTypeNetInterface,
  3211. InterfaceInfo->Id,
  3212. InterfaceInfo->Name,
  3213. &created
  3214. );
  3215. if (netInterface == NULL) {
  3216. status = GetLastError();
  3217. ClRtlLogPrint(LOG_CRITICAL,
  3218. "[NM] Failed to create object for interface %1!ws!, status %2!u!\n",
  3219. InterfaceInfo->Id,
  3220. status
  3221. );
  3222. goto error_exit;
  3223. }
  3224. CL_ASSERT(created == TRUE);
  3225. //
  3226. // Initialize the interface object.
  3227. //
  3228. ZeroMemory(netInterface, sizeof(NM_INTERFACE));
  3229. netInterface->Network = network;
  3230. netInterface->Node = node;
  3231. netInterface->State = ClusterNetInterfaceUnavailable;
  3232. netInterface->Description = MIDL_user_allocate(
  3233. NM_WCSLEN(InterfaceInfo->Description)
  3234. );
  3235. if (netInterface->Description == NULL) {
  3236. status = ERROR_NOT_ENOUGH_MEMORY;
  3237. ClRtlLogPrint(LOG_CRITICAL,
  3238. "[NM] Failed to allocate memory.\n"
  3239. );
  3240. goto error_exit;
  3241. }
  3242. wcscpy(netInterface->Description, InterfaceInfo->Description);
  3243. netInterface->AdapterName = MIDL_user_allocate(
  3244. (wcslen(InterfaceInfo->AdapterName) + 1) *
  3245. sizeof(WCHAR)
  3246. );
  3247. if (netInterface->AdapterName == NULL) {
  3248. status = ERROR_NOT_ENOUGH_MEMORY;
  3249. ClRtlLogPrint(LOG_CRITICAL,
  3250. "[NM] Failed to allocate memory.\n"
  3251. );
  3252. goto error_exit;
  3253. }
  3254. wcscpy(netInterface->AdapterName, InterfaceInfo->AdapterName);
  3255. netInterface->AdapterId = MIDL_user_allocate(
  3256. (wcslen(InterfaceInfo->AdapterId) + 1) *
  3257. sizeof(WCHAR)
  3258. );
  3259. if (netInterface->AdapterId == NULL) {
  3260. status = ERROR_NOT_ENOUGH_MEMORY;
  3261. ClRtlLogPrint(LOG_CRITICAL,
  3262. "[NM] Failed to allocate memory.\n"
  3263. );
  3264. goto error_exit;
  3265. }
  3266. wcscpy(netInterface->AdapterId, InterfaceInfo->AdapterId);
  3267. netInterface->Address = MIDL_user_allocate(
  3268. (wcslen(InterfaceInfo->Address) + 1) *
  3269. sizeof(WCHAR)
  3270. );
  3271. if (netInterface->Address == NULL) {
  3272. status = ERROR_NOT_ENOUGH_MEMORY;
  3273. ClRtlLogPrint(LOG_CRITICAL,
  3274. "[NM] Failed to allocate memory.\n"
  3275. );
  3276. goto error_exit;
  3277. }
  3278. wcscpy(netInterface->Address, InterfaceInfo->Address);
  3279. status = ClRtlTcpipStringToAddress(
  3280. InterfaceInfo->Address,
  3281. &(netInterface->BinaryAddress)
  3282. );
  3283. if (status != ERROR_SUCCESS) {
  3284. ClRtlLogPrint(LOG_UNUSUAL,
  3285. "[NM] Failed to convert interface address string %1!ws! to binary, status %2!u!.\n",
  3286. InterfaceInfo->Address,
  3287. status
  3288. );
  3289. goto error_exit;
  3290. }
  3291. netInterface->ClusnetEndpoint =
  3292. MIDL_user_allocate(
  3293. (wcslen(InterfaceInfo->ClusnetEndpoint) + 1) * sizeof(WCHAR)
  3294. );
  3295. if (netInterface->ClusnetEndpoint == NULL) {
  3296. status = ERROR_NOT_ENOUGH_MEMORY;
  3297. ClRtlLogPrint(LOG_CRITICAL,
  3298. "[NM] Failed to allocate memory.\n"
  3299. );
  3300. goto error_exit;
  3301. }
  3302. wcscpy(netInterface->ClusnetEndpoint, InterfaceInfo->ClusnetEndpoint);
  3303. NmpAcquireLock();
  3304. //
  3305. // Assign an index into the network's connectivity vector.
  3306. //
  3307. if (InterfaceInfo->NetIndex == NmInvalidInterfaceNetIndex) {
  3308. //
  3309. // Need to pick an index for this interface. Search for a free
  3310. // entry in the network's connectivity vector.
  3311. //
  3312. DWORD i;
  3313. PNM_CONNECTIVITY_VECTOR vector = network->ConnectivityVector;
  3314. for ( i=0; i<vector->EntryCount; i++) {
  3315. if ( vector->Data[i] ==
  3316. (NM_STATE_ENTRY) ClusterNetInterfaceStateUnknown
  3317. )
  3318. {
  3319. break;
  3320. }
  3321. }
  3322. netInterface->NetIndex = i;
  3323. ClRtlLogPrint(LOG_NOISE,
  3324. "[NM] Assigned index %1!u! to interface %2!ws!.\n",
  3325. netInterface->NetIndex,
  3326. InterfaceInfo->Id
  3327. );
  3328. }
  3329. else {
  3330. //
  3331. // Use the index that was already assigned by our peers.
  3332. //
  3333. netInterface->NetIndex = InterfaceInfo->NetIndex;
  3334. ClRtlLogPrint(LOG_NOISE,
  3335. "[NM] Using preassigned index %1!u! for interface %2!ws!.\n",
  3336. netInterface->NetIndex,
  3337. InterfaceInfo->Id
  3338. );
  3339. }
  3340. if (netInterface->NetIndex >= network->ConnectivityVector->EntryCount) {
  3341. //
  3342. // Grow the connectivity vector by the required number of entries.
  3343. //
  3344. PNM_STATE_ENTRY oldMatrixEntry, newMatrixEntry;
  3345. DWORD i;
  3346. PNM_CONNECTIVITY_VECTOR oldConnectivityVector =
  3347. network->ConnectivityVector;
  3348. PNM_CONNECTIVITY_VECTOR newConnectivityVector;
  3349. PNM_STATE_WORK_VECTOR oldStateVector = network->StateWorkVector;
  3350. PNM_STATE_WORK_VECTOR newStateVector;
  3351. PNM_CONNECTIVITY_MATRIX newMatrix;
  3352. DWORD oldVectorSize =
  3353. oldConnectivityVector->EntryCount;
  3354. DWORD newVectorSize = netInterface->NetIndex + 1;
  3355. //
  3356. // Note that one vector entry is included
  3357. // in sizeof(NM_CONNECTIVITY_VECTOR).
  3358. //
  3359. newConnectivityVector = LocalAlloc(
  3360. LMEM_FIXED,
  3361. ( sizeof(NM_CONNECTIVITY_VECTOR) +
  3362. ( (newVectorSize - 1) *
  3363. sizeof(NM_STATE_ENTRY)
  3364. )
  3365. ));
  3366. if (newConnectivityVector == NULL) {
  3367. status = ERROR_NOT_ENOUGH_MEMORY;
  3368. NmpReleaseLock();
  3369. ClRtlLogPrint(LOG_CRITICAL,
  3370. "[NM] Failed to allocate memory for connectivity vector\n"
  3371. );
  3372. goto error_exit;
  3373. }
  3374. //
  3375. // Initialize the new vector
  3376. //
  3377. newConnectivityVector->EntryCount = newVectorSize;
  3378. CopyMemory(
  3379. &(newConnectivityVector->Data[0]),
  3380. &(oldConnectivityVector->Data[0]),
  3381. oldVectorSize * sizeof(NM_STATE_ENTRY)
  3382. );
  3383. FillMemory(
  3384. &(newConnectivityVector->Data[oldVectorSize]),
  3385. (newVectorSize - oldVectorSize) * sizeof(NM_STATE_ENTRY),
  3386. (UCHAR) ClusterNetInterfaceStateUnknown
  3387. );
  3388. //
  3389. // Grow the state work vector
  3390. //
  3391. newStateVector = LocalAlloc(
  3392. LMEM_FIXED,
  3393. newVectorSize * sizeof(NM_STATE_WORK_ENTRY)
  3394. );
  3395. if (newStateVector == NULL) {
  3396. status = ERROR_NOT_ENOUGH_MEMORY;
  3397. NmpReleaseLock();
  3398. LocalFree(newConnectivityVector);
  3399. ClRtlLogPrint(LOG_CRITICAL,
  3400. "[NM] Failed to allocate memory for state work vector\n"
  3401. );
  3402. goto error_exit;
  3403. }
  3404. CopyMemory(
  3405. &(newStateVector[0]),
  3406. &(oldStateVector[0]),
  3407. oldVectorSize * sizeof(NM_STATE_WORK_ENTRY)
  3408. );
  3409. for (i=oldVectorSize; i<newVectorSize; i++) {
  3410. newStateVector[i].State =
  3411. (NM_STATE_ENTRY) ClusterNetInterfaceStateUnknown;
  3412. }
  3413. //
  3414. // Grow the network connecivitity matrix
  3415. //
  3416. newMatrix = LocalAlloc(
  3417. LMEM_FIXED,
  3418. NM_SIZEOF_CONNECTIVITY_MATRIX(newVectorSize)
  3419. );
  3420. if (newMatrix == NULL) {
  3421. status = ERROR_NOT_ENOUGH_MEMORY;
  3422. NmpReleaseLock();
  3423. LocalFree(newConnectivityVector);
  3424. LocalFree(newStateVector);
  3425. ClRtlLogPrint(LOG_CRITICAL,
  3426. "[NM] Failed to allocate memory for connectivity matrix\n"
  3427. );
  3428. goto error_exit;
  3429. }
  3430. //
  3431. // Initialize the new matrix
  3432. //
  3433. FillMemory(
  3434. newMatrix,
  3435. NM_SIZEOF_CONNECTIVITY_MATRIX(newVectorSize),
  3436. (UCHAR) ClusterNetInterfaceStateUnknown
  3437. );
  3438. oldMatrixEntry = network->ConnectivityMatrix;
  3439. newMatrixEntry = newMatrix;
  3440. for (i=0; i<oldVectorSize; i++) {
  3441. CopyMemory(
  3442. newMatrixEntry,
  3443. oldMatrixEntry,
  3444. oldVectorSize * sizeof(NM_STATE_ENTRY)
  3445. );
  3446. //
  3447. // Move the pointers to the next vector
  3448. //
  3449. oldMatrixEntry = NM_NEXT_CONNECTIVITY_MATRIX_ROW(
  3450. oldMatrixEntry,
  3451. oldVectorSize
  3452. );
  3453. newMatrixEntry = NM_NEXT_CONNECTIVITY_MATRIX_ROW(
  3454. newMatrixEntry,
  3455. newVectorSize
  3456. );
  3457. }
  3458. //
  3459. // Swap the pointers
  3460. //
  3461. LocalFree(network->ConnectivityVector);
  3462. network->ConnectivityVector = newConnectivityVector;
  3463. LocalFree(network->StateWorkVector);
  3464. network->StateWorkVector = newStateVector;
  3465. LocalFree(network->ConnectivityMatrix);
  3466. network->ConnectivityMatrix = newMatrix;
  3467. }
  3468. //
  3469. // Initialize the connectivity data for this interface
  3470. //
  3471. NmpSetInterfaceConnectivityData(
  3472. network,
  3473. netInterface->NetIndex,
  3474. ClusterNetInterfaceUnavailable
  3475. );
  3476. //
  3477. // Link the interface object onto the various object lists
  3478. //
  3479. InsertTailList(&(node->InterfaceList), &(netInterface->NodeLinkage));
  3480. node->InterfaceCount++;
  3481. InsertTailList(&(network->InterfaceList), &(netInterface->NetworkLinkage));
  3482. network->InterfaceCount++;
  3483. InsertTailList(&NmpInterfaceList, &(netInterface->Linkage));
  3484. NmpInterfaceCount++;
  3485. OmInsertObject(netInterface);
  3486. netInterface->Flags |= NM_FLAG_OM_INSERTED;
  3487. //
  3488. // Remember the interface for the local node.
  3489. //
  3490. if (node == NmLocalNode) {
  3491. network->LocalInterface = netInterface;
  3492. }
  3493. //
  3494. // Register with the cluster transport if needed.
  3495. //
  3496. if (NmpIsNetworkEnabledForUse(network)) {
  3497. if (node == NmLocalNode) {
  3498. //
  3499. // This is the local node. Register the network and all
  3500. // its interfaces with the cluster transport.
  3501. //
  3502. status = NmpRegisterNetwork(network, RetryOnFailure);
  3503. if (status != ERROR_SUCCESS) {
  3504. NmpReleaseLock();
  3505. goto error_exit;
  3506. }
  3507. }
  3508. else if (NmpIsNetworkRegistered(network)) {
  3509. //
  3510. // Just register this interface.
  3511. //
  3512. status = NmpRegisterInterface(netInterface, RetryOnFailure);
  3513. if (status != ERROR_SUCCESS) {
  3514. NmpReleaseLock();
  3515. goto error_exit;
  3516. }
  3517. }
  3518. }
  3519. //
  3520. // Put an additional reference on the object for the caller.
  3521. //
  3522. OmReferenceObject(netInterface);
  3523. NmpReleaseLock();
  3524. return(netInterface);
  3525. error_exit:
  3526. if (netInterface != NULL) {
  3527. NmpAcquireLock();
  3528. NmpDeleteInterfaceObject(netInterface, FALSE);
  3529. NmpReleaseLock();
  3530. }
  3531. SetLastError(status);
  3532. return(NULL);
  3533. } // NmpCreateInterfaceObject
  3534. DWORD
  3535. NmpGetInterfaceObjectInfo1(
  3536. IN PNM_INTERFACE Interface,
  3537. IN OUT PNM_INTERFACE_INFO InterfaceInfo1
  3538. )
  3539. /*++
  3540. Routine Description:
  3541. Reads information about a defined cluster network interface from the
  3542. interface object and fills in a structure describing it.
  3543. Arguments:
  3544. Interface - A pointer to the interface object to query.
  3545. InterfaceInfo - A pointer to the structure to fill in with node
  3546. information.
  3547. Return Value:
  3548. ERROR_SUCCESS if the routine succeeds.
  3549. A Win32 error code otherwise.
  3550. Notes:
  3551. Called with NmpLock held.
  3552. --*/
  3553. {
  3554. DWORD status;
  3555. NM_INTERFACE_INFO2 interfaceInfo2;
  3556. //
  3557. // Call the V2.0 routine and translate.
  3558. //
  3559. ZeroMemory(&interfaceInfo2, sizeof(interfaceInfo2));
  3560. status = NmpGetInterfaceObjectInfo(Interface, &interfaceInfo2);
  3561. if (status == ERROR_SUCCESS) {
  3562. CopyMemory(InterfaceInfo1, &interfaceInfo2, sizeof(NM_INTERFACE_INFO));
  3563. }
  3564. //
  3565. // Free the unused V2 fields
  3566. //
  3567. midl_user_free(interfaceInfo2.AdapterId);
  3568. return(status);
  3569. } // NmpGetInterfaceObjectInfo1
  3570. DWORD
  3571. NmpGetInterfaceObjectInfo(
  3572. IN PNM_INTERFACE Interface,
  3573. IN OUT PNM_INTERFACE_INFO2 InterfaceInfo
  3574. )
  3575. /*++
  3576. Routine Description:
  3577. Reads information about a defined cluster network interface from the
  3578. interface object and fills in a structure describing it.
  3579. Arguments:
  3580. Interface - A pointer to the interface object to query.
  3581. InterfaceInfo - A pointer to the structure to fill in with node
  3582. information.
  3583. Return Value:
  3584. ERROR_SUCCESS if the routine succeeds.
  3585. A Win32 error code otherwise.
  3586. Notes:
  3587. Called with NmpLock held.
  3588. --*/
  3589. {
  3590. LPWSTR tmpString = NULL;
  3591. LPWSTR interfaceId = (LPWSTR) OmObjectId(Interface);
  3592. LPWSTR interfaceName = (LPWSTR) OmObjectName(Interface);
  3593. LPWSTR nodeId = (LPWSTR) OmObjectId(Interface->Node);
  3594. LPWSTR networkId = (LPWSTR) OmObjectId(Interface->Network);
  3595. tmpString = MIDL_user_allocate(NM_WCSLEN(interfaceId));
  3596. if (tmpString == NULL) {
  3597. goto error_exit;
  3598. }
  3599. wcscpy(tmpString, interfaceId);
  3600. InterfaceInfo->Id = tmpString;
  3601. tmpString = MIDL_user_allocate(NM_WCSLEN(interfaceName));
  3602. if (tmpString == NULL) {
  3603. goto error_exit;
  3604. }
  3605. wcscpy(tmpString, interfaceName);
  3606. InterfaceInfo->Name = tmpString;
  3607. tmpString = MIDL_user_allocate(NM_WCSLEN(Interface->Description));
  3608. if (tmpString == NULL) {
  3609. goto error_exit;
  3610. }
  3611. wcscpy(tmpString, Interface->Description);
  3612. InterfaceInfo->Description = tmpString;
  3613. tmpString = MIDL_user_allocate(NM_WCSLEN(nodeId));
  3614. if (tmpString == NULL) {
  3615. goto error_exit;
  3616. }
  3617. wcscpy(tmpString, nodeId);
  3618. InterfaceInfo->NodeId = tmpString;
  3619. tmpString = MIDL_user_allocate(NM_WCSLEN(networkId));
  3620. if (tmpString == NULL) {
  3621. goto error_exit;
  3622. }
  3623. wcscpy(tmpString, networkId);
  3624. InterfaceInfo->NetworkId = tmpString;
  3625. tmpString = MIDL_user_allocate(NM_WCSLEN(Interface->AdapterName));
  3626. if (tmpString == NULL) {
  3627. goto error_exit;
  3628. }
  3629. wcscpy(tmpString, Interface->AdapterName);
  3630. InterfaceInfo->AdapterName = tmpString;
  3631. tmpString = MIDL_user_allocate(NM_WCSLEN(Interface->AdapterId));
  3632. if (tmpString == NULL) {
  3633. goto error_exit;
  3634. }
  3635. wcscpy(tmpString, Interface->AdapterId);
  3636. InterfaceInfo->AdapterId = tmpString;
  3637. tmpString = MIDL_user_allocate(NM_WCSLEN(Interface->Address));
  3638. if (tmpString == NULL) {
  3639. goto error_exit;
  3640. }
  3641. wcscpy(tmpString, Interface->Address);
  3642. InterfaceInfo->Address = tmpString;
  3643. tmpString = MIDL_user_allocate(NM_WCSLEN(Interface->ClusnetEndpoint));
  3644. if (tmpString == NULL) {
  3645. goto error_exit;
  3646. }
  3647. wcscpy(tmpString, Interface->ClusnetEndpoint);
  3648. InterfaceInfo->ClusnetEndpoint = tmpString;
  3649. InterfaceInfo->State = Interface->State;
  3650. InterfaceInfo->NetIndex = Interface->NetIndex;
  3651. return(ERROR_SUCCESS);
  3652. error_exit:
  3653. ClNetFreeInterfaceInfo(InterfaceInfo);
  3654. return(ERROR_NOT_ENOUGH_MEMORY);
  3655. } // NmpGetInterfaceObjectInfo2
  3656. VOID
  3657. NmpDeleteInterfaceObject(
  3658. IN PNM_INTERFACE Interface,
  3659. IN BOOLEAN IssueEvent
  3660. )
  3661. /*++
  3662. Notes:
  3663. Called with NM global lock held.
  3664. --*/
  3665. {
  3666. LPWSTR interfaceId = (LPWSTR) OmObjectId(Interface);
  3667. PNM_NETWORK network = Interface->Network;
  3668. if (NM_DELETE_PENDING(Interface)) {
  3669. CL_ASSERT(!NM_OM_INSERTED(Interface));
  3670. return;
  3671. }
  3672. ClRtlLogPrint(LOG_NOISE,
  3673. "[NM] deleting object for interface %1!ws!\n",
  3674. interfaceId
  3675. );
  3676. Interface->Flags |= NM_FLAG_DELETE_PENDING;
  3677. if (NM_OM_INSERTED(Interface)) {
  3678. //
  3679. // Remove the interface from the various object lists.
  3680. //
  3681. DWORD status = OmRemoveObject(Interface);
  3682. CL_ASSERT(status == ERROR_SUCCESS);
  3683. RemoveEntryList(&(Interface->Linkage));
  3684. CL_ASSERT(NmpInterfaceCount > 0);
  3685. NmpInterfaceCount--;
  3686. RemoveEntryList(&(Interface->NetworkLinkage));
  3687. CL_ASSERT(network->InterfaceCount > 0);
  3688. network->InterfaceCount--;
  3689. RemoveEntryList(&(Interface->NodeLinkage));
  3690. CL_ASSERT(Interface->Node->InterfaceCount > 0);
  3691. Interface->Node->InterfaceCount--;
  3692. Interface->Flags &= ~NM_FLAG_OM_INSERTED;
  3693. }
  3694. //
  3695. // Place the object on the deleted list
  3696. //
  3697. #if DBG
  3698. {
  3699. PLIST_ENTRY entry;
  3700. for ( entry = NmpDeletedInterfaceList.Flink;
  3701. entry != &NmpDeletedInterfaceList;
  3702. entry = entry->Flink
  3703. )
  3704. {
  3705. if (entry == &(Interface->Linkage)) {
  3706. break;
  3707. }
  3708. }
  3709. CL_ASSERT(entry != &(Interface->Linkage));
  3710. }
  3711. #endif DBG
  3712. InsertTailList(&NmpDeletedInterfaceList, &(Interface->Linkage));
  3713. if (network != NULL) {
  3714. if ( (Interface->Node != NULL) &&
  3715. NmpIsNetworkEnabledForUse(network)
  3716. )
  3717. {
  3718. DWORD status;
  3719. //
  3720. // Deregister the interface from the cluster transport
  3721. //
  3722. if ( (network->LocalInterface == Interface) &&
  3723. NmpIsNetworkRegistered(network)
  3724. )
  3725. {
  3726. //
  3727. // Deregister the network and all of its interfaces
  3728. //
  3729. NmpDeregisterNetwork(network);
  3730. }
  3731. else if (NmpIsInterfaceRegistered(Interface)) {
  3732. //
  3733. // Just deregister this interface
  3734. //
  3735. NmpDeregisterInterface(Interface);
  3736. }
  3737. }
  3738. //
  3739. // Invalidate the connectivity data for the interface.
  3740. //
  3741. NmpSetInterfaceConnectivityData(
  3742. network,
  3743. Interface->NetIndex,
  3744. ClusterNetInterfaceStateUnknown
  3745. );
  3746. if (network->LocalInterface == Interface) {
  3747. network->LocalInterface = NULL;
  3748. network->Flags &= ~NM_NET_IF_WORK_FLAGS;
  3749. }
  3750. //
  3751. // If this is not the last interface on the network,
  3752. // then update the network state.
  3753. //
  3754. if ((network->InterfaceCount != 0) &&
  3755. (NmpLeaderNodeId == NmLocalNodeId)) {
  3756. NmpScheduleNetworkStateRecalc(network);
  3757. }
  3758. }
  3759. if (IssueEvent) {
  3760. ClRtlLogPrint(LOG_NOISE,
  3761. "[NM] Issuing interface deleted event for interface %1!ws!.\n",
  3762. interfaceId
  3763. );
  3764. ClusterEvent(CLUSTER_EVENT_NETINTERFACE_DELETED, Interface);
  3765. }
  3766. //
  3767. // Remove the initial reference so the object can be destroyed.
  3768. //
  3769. OmDereferenceObject(Interface);
  3770. return;
  3771. } // NmpDeleteInterfaceObject
  3772. BOOL
  3773. NmpDestroyInterfaceObject(
  3774. PNM_INTERFACE Interface
  3775. )
  3776. {
  3777. DWORD status;
  3778. ClRtlLogPrint(LOG_NOISE,
  3779. "[NM] destroying object for interface %1!ws!\n",
  3780. (LPWSTR) OmObjectId(Interface)
  3781. );
  3782. CL_ASSERT(NM_DELETE_PENDING(Interface));
  3783. CL_ASSERT(!NM_OM_INSERTED(Interface));
  3784. //
  3785. // Remove the interface from the deleted list
  3786. //
  3787. #if DBG
  3788. {
  3789. PLIST_ENTRY entry;
  3790. for ( entry = NmpDeletedInterfaceList.Flink;
  3791. entry != &NmpDeletedInterfaceList;
  3792. entry = entry->Flink
  3793. )
  3794. {
  3795. if (entry == &(Interface->Linkage)) {
  3796. break;
  3797. }
  3798. }
  3799. CL_ASSERT(entry == &(Interface->Linkage));
  3800. }
  3801. #endif DBG
  3802. RemoveEntryList(&(Interface->Linkage));
  3803. //
  3804. // Dereference the node and network objects
  3805. //
  3806. if (Interface->Node != NULL) {
  3807. OmDereferenceObject(Interface->Node);
  3808. }
  3809. if (Interface->Network != NULL) {
  3810. OmDereferenceObject(Interface->Network);
  3811. }
  3812. //
  3813. // Free storage used by the object fields.
  3814. //
  3815. NM_FREE_OBJECT_FIELD(Interface, Description);
  3816. NM_FREE_OBJECT_FIELD(Interface, AdapterName);
  3817. NM_FREE_OBJECT_FIELD(Interface, AdapterId);
  3818. NM_FREE_OBJECT_FIELD(Interface, Address);
  3819. NM_FREE_OBJECT_FIELD(Interface, ClusnetEndpoint);
  3820. return(TRUE);
  3821. } // NmpDestroyInterfaceObject
  3822. DWORD
  3823. NmpEnumInterfaceObjects1(
  3824. OUT PNM_INTERFACE_ENUM * InterfaceEnum1
  3825. )
  3826. /*++
  3827. Routine Description:
  3828. Reads interface information for all defined cluster networks
  3829. and fills in an enumeration structure.
  3830. Arguments:
  3831. InterfaceEnum1 - A pointer to the variable into which to place a
  3832. pointer to the allocated interface enumeration.
  3833. Return Value:
  3834. ERROR_SUCCESS if the routine succeeds.
  3835. A Win32 error code otherwise.
  3836. Notes:
  3837. Called with the NmpLock held.
  3838. --*/
  3839. {
  3840. DWORD status = ERROR_SUCCESS;
  3841. PNM_INTERFACE_ENUM interfaceEnum1 = NULL;
  3842. DWORD i;
  3843. DWORD valueLength;
  3844. PLIST_ENTRY entry;
  3845. PNM_INTERFACE netInterface;
  3846. *InterfaceEnum1 = NULL;
  3847. if (NmpInterfaceCount == 0) {
  3848. valueLength = sizeof(NM_INTERFACE_ENUM);
  3849. }
  3850. else {
  3851. valueLength =
  3852. sizeof(NM_INTERFACE_ENUM) +
  3853. (sizeof(NM_INTERFACE_INFO) * (NmpInterfaceCount - 1));
  3854. }
  3855. interfaceEnum1 = MIDL_user_allocate(valueLength);
  3856. if (interfaceEnum1 == NULL) {
  3857. return(ERROR_NOT_ENOUGH_MEMORY);
  3858. }
  3859. ZeroMemory(interfaceEnum1, valueLength);
  3860. for (entry = NmpInterfaceList.Flink, i=0;
  3861. entry != &NmpInterfaceList;
  3862. entry = entry->Flink, i++
  3863. )
  3864. {
  3865. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, Linkage);
  3866. status = NmpGetInterfaceObjectInfo1(
  3867. netInterface,
  3868. &(interfaceEnum1->InterfaceList[i])
  3869. );
  3870. if (status != ERROR_SUCCESS) {
  3871. ClNetFreeInterfaceEnum1(interfaceEnum1);
  3872. return(status);
  3873. }
  3874. }
  3875. interfaceEnum1->InterfaceCount = NmpInterfaceCount;
  3876. *InterfaceEnum1 = interfaceEnum1;
  3877. return(ERROR_SUCCESS);
  3878. } // NmpEnumInterfaceObjects1
  3879. DWORD
  3880. NmpEnumInterfaceObjects(
  3881. OUT PNM_INTERFACE_ENUM2 * InterfaceEnum
  3882. )
  3883. /*++
  3884. Routine Description:
  3885. Reads interface information for all defined cluster networks
  3886. and fills in an enumeration structure.
  3887. Arguments:
  3888. InterfaceEnum - A pointer to the variable into which to place a
  3889. pointer to the allocated interface enumeration.
  3890. Return Value:
  3891. ERROR_SUCCESS if the routine succeeds.
  3892. A Win32 error code otherwise.
  3893. Notes:
  3894. Called with the NmpLock held.
  3895. --*/
  3896. {
  3897. DWORD status = ERROR_SUCCESS;
  3898. PNM_INTERFACE_ENUM2 interfaceEnum = NULL;
  3899. DWORD i;
  3900. DWORD valueLength;
  3901. PLIST_ENTRY entry;
  3902. PNM_INTERFACE netInterface;
  3903. *InterfaceEnum = NULL;
  3904. if (NmpInterfaceCount == 0) {
  3905. valueLength = sizeof(NM_INTERFACE_ENUM2);
  3906. }
  3907. else {
  3908. valueLength =
  3909. sizeof(NM_INTERFACE_ENUM2) +
  3910. (sizeof(NM_INTERFACE_INFO2) * (NmpInterfaceCount - 1));
  3911. }
  3912. interfaceEnum = MIDL_user_allocate(valueLength);
  3913. if (interfaceEnum == NULL) {
  3914. return(ERROR_NOT_ENOUGH_MEMORY);
  3915. }
  3916. ZeroMemory(interfaceEnum, valueLength);
  3917. for (entry = NmpInterfaceList.Flink, i=0;
  3918. entry != &NmpInterfaceList;
  3919. entry = entry->Flink, i++
  3920. )
  3921. {
  3922. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, Linkage);
  3923. status = NmpGetInterfaceObjectInfo(
  3924. netInterface,
  3925. &(interfaceEnum->InterfaceList[i])
  3926. );
  3927. if (status != ERROR_SUCCESS) {
  3928. ClNetFreeInterfaceEnum((PNM_INTERFACE_ENUM2) interfaceEnum);
  3929. return(status);
  3930. }
  3931. }
  3932. interfaceEnum->InterfaceCount = NmpInterfaceCount;
  3933. *InterfaceEnum = interfaceEnum;
  3934. return(ERROR_SUCCESS);
  3935. } // NmpEnumInterfaceObjects
  3936. DWORD
  3937. NmpEnumInterfaceObjectStates(
  3938. OUT PNM_INTERFACE_STATE_ENUM * InterfaceStateEnum
  3939. )
  3940. /*++
  3941. Routine Description:
  3942. Reads state information for all defined cluster network interfaces
  3943. and fills in an enumeration structure.
  3944. Arguments:
  3945. InterfaceStateEnum - A pointer to the variable into which to place a
  3946. pointer to the allocated interface enumeration.
  3947. Return Value:
  3948. ERROR_SUCCESS if the routine succeeds.
  3949. A Win32 error code otherwise.
  3950. Notes:
  3951. Called with the NmpLock held.
  3952. --*/
  3953. {
  3954. DWORD status = ERROR_SUCCESS;
  3955. PNM_INTERFACE_STATE_ENUM interfaceStateEnum = NULL;
  3956. PNM_INTERFACE_STATE_INFO interfaceStateInfo;
  3957. DWORD i;
  3958. DWORD valueLength;
  3959. PLIST_ENTRY entry;
  3960. PNM_INTERFACE netInterface;
  3961. LPWSTR interfaceId;
  3962. *InterfaceStateEnum = NULL;
  3963. if (NmpInterfaceCount == 0) {
  3964. valueLength = sizeof(NM_INTERFACE_STATE_ENUM);
  3965. }
  3966. else {
  3967. valueLength =
  3968. sizeof(NM_INTERFACE_STATE_ENUM) +
  3969. (sizeof(NM_INTERFACE_STATE_INFO) * (NmpInterfaceCount - 1));
  3970. }
  3971. interfaceStateEnum = MIDL_user_allocate(valueLength);
  3972. if (interfaceStateEnum == NULL) {
  3973. return(ERROR_NOT_ENOUGH_MEMORY);
  3974. }
  3975. ZeroMemory(interfaceStateEnum, valueLength);
  3976. for (entry = NmpInterfaceList.Flink, i=0;
  3977. entry != &NmpInterfaceList;
  3978. entry = entry->Flink, i++
  3979. )
  3980. {
  3981. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, Linkage);
  3982. interfaceId = (LPWSTR) OmObjectId(netInterface);
  3983. interfaceStateInfo = &(interfaceStateEnum->InterfaceList[i]);
  3984. interfaceStateInfo->State = netInterface->State;
  3985. interfaceStateInfo->Id = MIDL_user_allocate(NM_WCSLEN(interfaceId));
  3986. if (interfaceStateInfo->Id == NULL) {
  3987. NmpFreeInterfaceStateEnum(interfaceStateEnum);
  3988. return(ERROR_NOT_ENOUGH_MEMORY);
  3989. }
  3990. lstrcpyW(interfaceStateInfo->Id, interfaceId);
  3991. }
  3992. interfaceStateEnum->InterfaceCount = NmpInterfaceCount;
  3993. *InterfaceStateEnum = interfaceStateEnum;
  3994. return(ERROR_SUCCESS);
  3995. } // NmpEnumInterfaceObjectStates
  3996. /////////////////////////////////////////////////////////////////////////////
  3997. //
  3998. // State Management routines
  3999. //
  4000. /////////////////////////////////////////////////////////////////////////////
  4001. VOID
  4002. NmpSetInterfaceConnectivityData(
  4003. PNM_NETWORK Network,
  4004. DWORD InterfaceNetIndex,
  4005. CLUSTER_NETINTERFACE_STATE State
  4006. )
  4007. {
  4008. PNM_CONNECTIVITY_MATRIX matrixEntry;
  4009. Network->ConnectivityVector->Data[InterfaceNetIndex] =
  4010. (NM_STATE_ENTRY) State;
  4011. Network->StateWorkVector[InterfaceNetIndex].State =
  4012. (NM_STATE_ENTRY) State;
  4013. matrixEntry = NM_GET_CONNECTIVITY_MATRIX_ENTRY(
  4014. Network->ConnectivityMatrix,
  4015. InterfaceNetIndex,
  4016. InterfaceNetIndex,
  4017. Network->ConnectivityVector->EntryCount
  4018. );
  4019. *matrixEntry = (NM_STATE_ENTRY)State;
  4020. return;
  4021. } // NmpSetInterfaceConnectivityData
  4022. VOID
  4023. NmpReportLocalInterfaceStateEvent(
  4024. IN CL_NODE_ID NodeId,
  4025. IN CL_NETWORK_ID NetworkId,
  4026. IN DWORD NewState
  4027. )
  4028. {
  4029. PNM_INTERFACE netInterface;
  4030. NmpAcquireLock();
  4031. if (NmpLockedEnterApi(NmStateOnlinePending)){
  4032. netInterface = NmpGetInterfaceForNodeAndNetworkById(
  4033. NodeId,
  4034. NetworkId
  4035. );
  4036. if (netInterface != NULL) {
  4037. NmpProcessLocalInterfaceStateEvent(netInterface, NewState);
  4038. }
  4039. NmpLockedLeaveApi();
  4040. }
  4041. NmpReleaseLock();
  4042. return;
  4043. } // NmReportLocalInterfaceStateEvent
  4044. VOID
  4045. NmpProcessLocalInterfaceStateEvent(
  4046. IN PNM_INTERFACE Interface,
  4047. IN CLUSTER_NETINTERFACE_STATE NewState
  4048. )
  4049. /*+
  4050. Notes:
  4051. Called with the NmpLock held.
  4052. --*/
  4053. {
  4054. DWORD status;
  4055. PNM_NETWORK network = Interface->Network;
  4056. LPCWSTR interfaceId = OmObjectId(Interface);
  4057. LPCWSTR networkId = OmObjectId(network);
  4058. LPCWSTR networkName = OmObjectName(network);
  4059. PNM_NODE node = Interface->Node;
  4060. LPCWSTR nodeName = OmObjectName(node);
  4061. PNM_CONNECTIVITY_VECTOR vector = network->ConnectivityVector;
  4062. DWORD ifNetIndex = Interface->NetIndex;
  4063. //
  4064. // Filter out stale reports for dead nodes.
  4065. //
  4066. if ((node == NmLocalNode) || (node->State != ClusterNodeDown)) {
  4067. CL_ASSERT(
  4068. vector->Data[ifNetIndex] !=
  4069. (NM_STATE_ENTRY) ClusterNetInterfaceStateUnknown
  4070. );
  4071. //
  4072. // Apply the change to the local connectivity vector.
  4073. //
  4074. vector->Data[ifNetIndex] = (NM_STATE_ENTRY) NewState;
  4075. //
  4076. // Log an event
  4077. //
  4078. switch (NewState) {
  4079. case ClusterNetInterfaceUp:
  4080. //
  4081. // A local interface is now operational, or a remote interface
  4082. // is now reachable. Schedule an immediate connectivity report,
  4083. // since this event may avert failure of resources that depend
  4084. // on the interface.
  4085. //
  4086. if (node != NmLocalNode) {
  4087. ClRtlLogPrint(LOG_NOISE,
  4088. "[NM] Communication was (re)established with "
  4089. "interface %1!ws! (node: %2!ws!, network: %3!ws!)\n",
  4090. interfaceId,
  4091. nodeName,
  4092. networkName
  4093. );
  4094. CsLogEvent2(
  4095. LOG_NOISE,
  4096. NM_EVENT_NETINTERFACE_UP,
  4097. nodeName,
  4098. networkName
  4099. );
  4100. }
  4101. if (NmpLeaderNodeId == NmLocalNodeId) {
  4102. //
  4103. // This node is the leader. Call the handler routine
  4104. // directly.
  4105. //
  4106. NmpReportNetworkConnectivity(network);
  4107. }
  4108. else {
  4109. //
  4110. // We need to report to the leader.
  4111. // Defer to a worker thread.
  4112. //
  4113. NmpScheduleNetworkConnectivityReport(network);
  4114. }
  4115. break;
  4116. case ClusterNetInterfaceUnreachable:
  4117. //
  4118. // A remote interface is unreachable.
  4119. //
  4120. if (node != NmLocalNode) {
  4121. ClRtlLogPrint(LOG_UNUSUAL,
  4122. "[NM] Communication was lost with interface "
  4123. "%1!ws! (node: %2!ws!, network: %3!ws!)\n",
  4124. interfaceId,
  4125. nodeName,
  4126. networkName
  4127. );
  4128. CsLogEvent2(
  4129. LOG_UNUSUAL,
  4130. NM_EVENT_NETINTERFACE_UNREACHABLE,
  4131. nodeName,
  4132. networkName
  4133. );
  4134. }
  4135. if (NmpLeaderNodeId == NmLocalNodeId) {
  4136. //
  4137. // This node is the leader. Call the handler routine
  4138. // directly.
  4139. //
  4140. NmpReportNetworkConnectivity(network);
  4141. }
  4142. else {
  4143. //
  4144. // Schedule a delayed connectivity report in order to
  4145. // aggregate multiple failures.
  4146. //
  4147. NmpStartNetworkConnectivityReportTimer(network);
  4148. }
  4149. break;
  4150. case ClusterNetInterfaceFailed:
  4151. //
  4152. // A local interface has failed. Schedule an immediate
  4153. // connectivity report.
  4154. //
  4155. ClRtlLogPrint(LOG_UNUSUAL,
  4156. "[NM] Local interface %1!ws! on network %2!ws! "
  4157. "has failed\n",
  4158. interfaceId,
  4159. networkName
  4160. );
  4161. CsLogEvent1(
  4162. LOG_UNUSUAL,
  4163. NM_EVENT_NETINTERFACE_FAILED,
  4164. networkName
  4165. );
  4166. if (NmpLeaderNodeId == NmLocalNodeId) {
  4167. //
  4168. // This node is the leader. Call the handler routine
  4169. // directly.
  4170. //
  4171. NmpReportNetworkConnectivity(network);
  4172. }
  4173. else {
  4174. //
  4175. // We need to report to the leader. Defer to a worker thread.
  4176. //
  4177. NmpScheduleNetworkConnectivityReport(network);
  4178. }
  4179. break;
  4180. default:
  4181. break;
  4182. }
  4183. }
  4184. else {
  4185. ClRtlLogPrint(LOG_NOISE,
  4186. "[NM] Ignoring stale report from clusnet for interface %1!ws! (node: %2!ws!, network: %3!ws!).\n",
  4187. interfaceId,
  4188. nodeName,
  4189. networkName
  4190. );
  4191. }
  4192. return;
  4193. } // NmpProcessLocalInterfaceStateEvent
  4194. DWORD
  4195. NmpReportInterfaceConnectivity(
  4196. IN RPC_BINDING_HANDLE RpcBinding,
  4197. IN LPWSTR InterfaceId,
  4198. IN PNM_CONNECTIVITY_VECTOR ConnectivityVector,
  4199. IN LPWSTR NetworkId
  4200. )
  4201. /*++
  4202. Routine Description:
  4203. Sends a network connectivity report to the leader node via RPC.
  4204. Arguments:
  4205. RpcBinding - The RPC binding handle to use in the call to the leader.
  4206. InterfaceId - A pointer to a string that identifies the interface
  4207. to which the report applies.
  4208. ConnectivityVector - A pointer to the connectivity vector to be included
  4209. in the report.
  4210. NetworkId - A pointer to a string that identifies the network with
  4211. which the interface is associated.
  4212. Return Value:
  4213. A Win32 status code.
  4214. Notes:
  4215. Called with NM lock held.
  4216. Releases & reacquires NM lock during processing.
  4217. --*/
  4218. {
  4219. RPC_ASYNC_STATE rpcAsyncState;
  4220. DWORD status;
  4221. PNM_CONNECTIVITY_REPORT_CONTEXT context;
  4222. PNM_LEADER_CHANGE_WAIT_ENTRY waitEntry = NULL;
  4223. BOOL result;
  4224. ClRtlLogPrint(LOG_NOISE,
  4225. "[NM] Reporting connectivity to leader for network %1!ws!.\n",
  4226. NetworkId
  4227. );
  4228. //
  4229. // Allocate a context block for this report
  4230. //
  4231. context = LocalAlloc(
  4232. (LMEM_FIXED | LMEM_ZEROINIT),
  4233. sizeof(NM_CONNECTIVITY_REPORT_CONTEXT)
  4234. );
  4235. if (context == NULL) {
  4236. status = GetLastError();
  4237. ClRtlLogPrint(LOG_UNUSUAL,
  4238. "[NM] Failed to allocate connectivity report context, "
  4239. "status %1!u!.\n",
  4240. status
  4241. );
  4242. return(status);
  4243. }
  4244. context->ConnectivityReportEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  4245. if (context->ConnectivityReportEvent == NULL) {
  4246. status = GetLastError();
  4247. ClRtlLogPrint(LOG_CRITICAL,
  4248. "[NM] Unable to create event for connectivity report, "
  4249. "status %1!u!\n",
  4250. status
  4251. );
  4252. goto error_exit;
  4253. }
  4254. waitEntry = &(context->LeaderChangeWaitEntry);
  4255. waitEntry->LeaderChangeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  4256. if (waitEntry->LeaderChangeEvent == NULL) {
  4257. status = GetLastError();
  4258. ClRtlLogPrint(LOG_CRITICAL,
  4259. "[NM] Unable to create event for connectivity report, "
  4260. "status %1!u!\n",
  4261. status
  4262. );
  4263. goto error_exit;
  4264. }
  4265. //
  4266. // Initialize the status block for the async RPC call
  4267. //
  4268. status = RpcAsyncInitializeHandle(
  4269. &rpcAsyncState,
  4270. sizeof(rpcAsyncState)
  4271. );
  4272. if (status != RPC_S_OK) {
  4273. ClRtlLogPrint(LOG_UNUSUAL,
  4274. "[NM] Failed to initialize RPC status block for connectivity "
  4275. "report, status %1!u!.\n",
  4276. status
  4277. );
  4278. goto error_exit;
  4279. }
  4280. rpcAsyncState.NotificationType = RpcNotificationTypeEvent;
  4281. rpcAsyncState.u.hEvent = context->ConnectivityReportEvent;
  4282. result = ResetEvent(context->ConnectivityReportEvent);
  4283. CL_ASSERT(result != 0);
  4284. //
  4285. // Hook changes in the node leadership.
  4286. //
  4287. result = ResetEvent(waitEntry->LeaderChangeEvent);
  4288. CL_ASSERT(result != 0);
  4289. InsertTailList(&NmpLeaderChangeWaitList, &(waitEntry->Linkage));
  4290. NmpReleaseLock();
  4291. //
  4292. // Send the report to the leader
  4293. //
  4294. status = NmRpcReportInterfaceConnectivity(
  4295. &rpcAsyncState,
  4296. RpcBinding,
  4297. InterfaceId,
  4298. ConnectivityVector
  4299. );
  4300. if (status == RPC_S_OK) {
  4301. //
  4302. // The call is pending.
  4303. //
  4304. HANDLE waitHandles[2];
  4305. DWORD rpcStatus;
  4306. //
  4307. // Wait for the call to complete or a leadership change.
  4308. //
  4309. waitHandles[0] = context->ConnectivityReportEvent;
  4310. waitHandles[1] = waitEntry->LeaderChangeEvent;
  4311. status = WaitForMultipleObjects(
  4312. 2,
  4313. waitHandles,
  4314. FALSE,
  4315. INFINITE
  4316. );
  4317. if (status != WAIT_OBJECT_0) {
  4318. //
  4319. // The leadership changed. Cancel the RPC call.
  4320. //
  4321. // We would also go through this path if the wait failed for
  4322. // some reason, but that really should not happen. Either way,
  4323. // we should cancel the call.
  4324. //
  4325. CL_ASSERT(status == (WAIT_OBJECT_0 + 1));
  4326. ClRtlLogPrint(LOG_UNUSUAL,
  4327. "[NM] Leadership changed. Cancelling connectivity report for "
  4328. "network %1!ws!.\n",
  4329. NetworkId
  4330. );
  4331. rpcStatus = RpcAsyncCancelCall(&rpcAsyncState, TRUE);
  4332. CL_ASSERT(rpcStatus == RPC_S_OK);
  4333. //
  4334. // Wait for the call to complete.
  4335. //
  4336. status = WaitForSingleObject(
  4337. context->ConnectivityReportEvent,
  4338. INFINITE
  4339. );
  4340. CL_ASSERT(status == WAIT_OBJECT_0);
  4341. }
  4342. //
  4343. // At this point, the call should be complete. Get the completion
  4344. // status. Any RPC error will be returned in 'rpcStatus'. If there
  4345. // was no RPC error, then any application error will be returned
  4346. // in 'status'.
  4347. //
  4348. rpcStatus = RpcAsyncCompleteCall(&rpcAsyncState, &status);
  4349. if (rpcStatus != RPC_S_OK) {
  4350. //
  4351. // Either the call was cancelled or an RPC error
  4352. // occurred. The application status is irrelevant.
  4353. //
  4354. status = rpcStatus;
  4355. }
  4356. if (status == RPC_S_OK) {
  4357. ClRtlLogPrint(LOG_NOISE,
  4358. "[NM] Connectivity report completed successfully "
  4359. "for network %1!ws!.\n",
  4360. NetworkId
  4361. );
  4362. }
  4363. else if (status == RPC_S_CALL_CANCELLED) {
  4364. ClRtlLogPrint(LOG_UNUSUAL,
  4365. "[NM] Connectivity report was cancelled for "
  4366. "network %1!ws!.\n",
  4367. NetworkId
  4368. );
  4369. }
  4370. else {
  4371. ClRtlLogPrint(LOG_UNUSUAL,
  4372. "[NM] Connectivity report failed for network "
  4373. "%1!ws!, status %2!u!.\n",
  4374. NetworkId,
  4375. status
  4376. );
  4377. CL_ASSERT(status != RPC_S_ASYNC_CALL_PENDING);
  4378. }
  4379. }
  4380. else {
  4381. //
  4382. // A synchronous error was returned.
  4383. //
  4384. CL_ASSERT(status != RPC_S_ASYNC_CALL_PENDING);
  4385. ClRtlLogPrint(LOG_UNUSUAL,
  4386. "[NM] Connectivity report failed for network %1!ws!, "
  4387. "status %2!u!.\n",
  4388. NetworkId,
  4389. status
  4390. );
  4391. }
  4392. NmpAcquireLock();
  4393. error_exit:
  4394. //
  4395. // Free the context block
  4396. //
  4397. if (context != NULL) {
  4398. if (context->ConnectivityReportEvent != NULL) {
  4399. CloseHandle(context->ConnectivityReportEvent);
  4400. }
  4401. if (waitEntry != NULL && waitEntry->LeaderChangeEvent != NULL) {
  4402. //
  4403. // Remove our leadership change notification hook.
  4404. //
  4405. if (waitEntry->Linkage.Flink != NULL) {
  4406. RemoveEntryList(&(waitEntry->Linkage));
  4407. }
  4408. CloseHandle(waitEntry->LeaderChangeEvent);
  4409. }
  4410. LocalFree(context);
  4411. }
  4412. return(status);
  4413. } // NmpReportInterfaceConnectivity
  4414. VOID
  4415. NmpProcessInterfaceConnectivityReport(
  4416. IN PNM_INTERFACE SourceInterface,
  4417. IN PNM_CONNECTIVITY_VECTOR ConnectivityVector
  4418. )
  4419. /*+
  4420. Notes:
  4421. Called with NmpLock held.
  4422. --*/
  4423. {
  4424. PNM_NETWORK network = SourceInterface->Network;
  4425. PNM_CONNECTIVITY_MATRIX matrix = network->ConnectivityMatrix;
  4426. DWORD entryCount;
  4427. PNM_NODE node = SourceInterface->Node;
  4428. PNM_CONNECTIVITY_VECTOR vector = network->ConnectivityVector;
  4429. DWORD ifNetIndex = SourceInterface->NetIndex;
  4430. //
  4431. // Filter out stale reports from dead nodes and for
  4432. // disabled/deleted networks.
  4433. //
  4434. if ( ((node == NmLocalNode) || (node->State != ClusterNodeDown)) &&
  4435. NmpIsNetworkEnabledForUse(network) &&
  4436. !NM_DELETE_PENDING(network)
  4437. )
  4438. {
  4439. //
  4440. // Update the network's connectivity matrix
  4441. //
  4442. if (network->ConnectivityVector->EntryCount <= vector->EntryCount) {
  4443. entryCount = network->ConnectivityVector->EntryCount;
  4444. }
  4445. else {
  4446. //
  4447. // An interface must have been added while this
  4448. // call was in flight. Ignore the missing data.
  4449. //
  4450. entryCount = ConnectivityVector->EntryCount;
  4451. }
  4452. CopyMemory(
  4453. NM_GET_CONNECTIVITY_MATRIX_ROW(
  4454. matrix,
  4455. ifNetIndex,
  4456. entryCount
  4457. ),
  4458. &(ConnectivityVector->Data[0]),
  4459. entryCount * sizeof(NM_STATE_ENTRY)
  4460. );
  4461. //
  4462. // If this is the leader node, and no NT4 nodes are in the cluster,
  4463. // schedule a state recalculation.
  4464. //
  4465. if (NmpLeaderNodeId == NmLocalNodeId) {
  4466. NmpStartNetworkStateRecalcTimer(
  4467. network,
  4468. NM_NET_STATE_RECALC_TIMEOUT
  4469. );
  4470. }
  4471. }
  4472. else {
  4473. ClRtlLogPrint(LOG_NOISE,
  4474. "[NM] Ignoring stale connectivity report from interface %1!ws!.\n",
  4475. OmObjectId(SourceInterface)
  4476. );
  4477. }
  4478. return;
  4479. } // NmpProcessInterfaceConnectivityReport
  4480. VOID
  4481. NmpFreeInterfaceStateEnum(
  4482. PNM_INTERFACE_STATE_ENUM InterfaceStateEnum
  4483. )
  4484. {
  4485. PNM_INTERFACE_STATE_INFO interfaceStateInfo;
  4486. DWORD i;
  4487. for (i=0; i<InterfaceStateEnum->InterfaceCount; i++) {
  4488. interfaceStateInfo = &(InterfaceStateEnum->InterfaceList[i]);
  4489. if (interfaceStateInfo->Id != NULL) {
  4490. MIDL_user_free(interfaceStateInfo->Id);
  4491. }
  4492. }
  4493. MIDL_user_free(InterfaceStateEnum);
  4494. return;
  4495. } // NmpFreeInterfaceStateEnum
  4496. BOOL
  4497. NmpIsAddressInAddressEnum(
  4498. ULONGLONG Address,
  4499. PNM_ADDRESS_ENUM AddressEnum
  4500. )
  4501. {
  4502. DWORD i;
  4503. for (i=0; i<AddressEnum->AddressCount; i++) {
  4504. if (AddressEnum->AddressList[i] == Address) {
  4505. return(TRUE);
  4506. }
  4507. }
  4508. return(FALSE);
  4509. } // NmpIsAddressInAddressEnum
  4510. DWORD
  4511. NmpBuildInterfaceOnlineAddressEnum(
  4512. PNM_INTERFACE Interface,
  4513. PNM_ADDRESS_ENUM * OnlineAddressEnum
  4514. )
  4515. /*++
  4516. Called with NmpLock held and Interface referenced.
  4517. --*/
  4518. {
  4519. DWORD status = ERROR_SUCCESS;
  4520. PNM_ADDRESS_ENUM onlineAddressEnum = NULL;
  4521. DWORD onlineAddressEnumSize;
  4522. PCLRTL_NET_ADAPTER_ENUM adapterEnum = NULL;
  4523. PCLRTL_NET_ADAPTER_INFO adapterInfo = NULL;
  4524. PCLRTL_NET_INTERFACE_INFO adapterIfInfo = NULL;
  4525. PNM_ADDRESS_ENUM onlineEnum = NULL;
  4526. DWORD onlineEnumSize;
  4527. *OnlineAddressEnum = NULL;
  4528. //
  4529. // Get the local network configuration.
  4530. //
  4531. adapterEnum = ClRtlEnumNetAdapters();
  4532. if (adapterEnum == NULL) {
  4533. status = GetLastError();
  4534. ClRtlLogPrint(LOG_UNUSUAL,
  4535. "[NM] Failed to obtain local network configuration, status %1!u!.\n",
  4536. status
  4537. );
  4538. return(status);
  4539. }
  4540. //
  4541. // Find the adapter for this interface
  4542. //
  4543. adapterInfo = ClRtlFindNetAdapterById(
  4544. adapterEnum,
  4545. Interface->AdapterId
  4546. );
  4547. if (adapterInfo == NULL) {
  4548. status = ERROR_NOT_FOUND;
  4549. ClRtlLogPrint(LOG_UNUSUAL,
  4550. "[NM] Failed to find adapter for interface %1!ws!, status %2!u!.\n",
  4551. status
  4552. );
  4553. goto error_exit;
  4554. }
  4555. //
  4556. // Allocate an address enum structure.
  4557. //
  4558. if (adapterInfo->InterfaceCount == 0) {
  4559. onlineEnumSize = sizeof(NM_ADDRESS_ENUM);
  4560. }
  4561. else {
  4562. onlineEnumSize = sizeof(NM_ADDRESS_ENUM) +
  4563. ( (adapterInfo->InterfaceCount - 1) *
  4564. sizeof(ULONGLONG)
  4565. );
  4566. }
  4567. onlineEnum = midl_user_allocate(onlineEnumSize);
  4568. if (onlineEnum == NULL) {
  4569. ClRtlLogPrint(LOG_UNUSUAL,
  4570. "[NM] Failed to allocate memory for ping list.\n"
  4571. );
  4572. status = ERROR_NOT_ENOUGH_MEMORY;
  4573. goto error_exit;
  4574. }
  4575. onlineEnum->AddressSize = sizeof(ULONG);
  4576. onlineEnum->AddressCount = 0;
  4577. for (adapterIfInfo = adapterInfo->InterfaceList;
  4578. adapterIfInfo != NULL;
  4579. adapterIfInfo = adapterIfInfo->Next
  4580. )
  4581. {
  4582. //
  4583. // Skip invalid addresses (0.0.0.0)
  4584. //
  4585. if (adapterIfInfo->InterfaceAddress != 0) {
  4586. onlineEnum->AddressList[onlineEnum->AddressCount++] =
  4587. (ULONGLONG) adapterIfInfo->InterfaceAddress;
  4588. ClRtlLogPrint(LOG_NOISE,
  4589. "[NM] Found address %1!ws! for interface %2!ws!.\n",
  4590. adapterIfInfo->InterfaceAddressString,
  4591. OmObjectId(Interface)
  4592. );
  4593. }
  4594. }
  4595. *OnlineAddressEnum = onlineEnum;
  4596. status = ERROR_SUCCESS;
  4597. error_exit:
  4598. if (adapterEnum != NULL) {
  4599. ClRtlFreeNetAdapterEnum(adapterEnum);
  4600. }
  4601. return(status);
  4602. } // NmpBuildInterfaceOnlineAddressEnum
  4603. DWORD
  4604. NmpBuildInterfacePingAddressEnum(
  4605. IN PNM_INTERFACE Interface,
  4606. IN PNM_ADDRESS_ENUM OnlineAddressEnum,
  4607. OUT PNM_ADDRESS_ENUM * PingAddressEnum
  4608. )
  4609. /*++
  4610. Called with NmpLock held and Interface referenced.
  4611. --*/
  4612. {
  4613. DWORD status = ERROR_SUCCESS;
  4614. PNM_NETWORK network = Interface->Network;
  4615. PMIB_IPFORWARDTABLE ipForwardTable = NULL;
  4616. PMIB_IPFORWARDROW ipRow, ipRowLimit;
  4617. PMIB_TCPTABLE tcpTable = NULL;
  4618. PMIB_TCPROW tcpRow, tcpRowLimit;
  4619. ULONG netAddress, netMask;
  4620. DWORD allocSize, tableSize;
  4621. BOOL duplicate;
  4622. DWORD i;
  4623. PNM_ADDRESS_ENUM pingEnum = NULL;
  4624. DWORD pingEnumSize;
  4625. *PingAddressEnum = NULL;
  4626. //
  4627. // Convert the network address & mask strings to binary
  4628. //
  4629. status = ClRtlTcpipStringToAddress(network->Address, &netAddress);
  4630. if (status != ERROR_SUCCESS) {
  4631. ClRtlLogPrint(LOG_UNUSUAL,
  4632. "[NM] Failed to convert network address string %1!ws! to binary, status %2!u!.\n",
  4633. network->Address,
  4634. status
  4635. );
  4636. return(status);
  4637. }
  4638. status = ClRtlTcpipStringToAddress(network->AddressMask, &netMask);
  4639. if (status != ERROR_SUCCESS) {
  4640. ClRtlLogPrint(LOG_UNUSUAL,
  4641. "[NM] Failed to convert network address mask string %1!ws! to binary, status %2!u!.\n",
  4642. network->AddressMask,
  4643. status
  4644. );
  4645. return(status);
  4646. }
  4647. //
  4648. // We don't need the lock for the rest of the function.
  4649. //
  4650. NmpReleaseLock();
  4651. //
  4652. // Allocate a ping enum structure
  4653. //
  4654. pingEnumSize = sizeof(NM_ADDRESS_ENUM) +
  4655. ((NM_MAX_IF_PING_ENUM_SIZE - 1) * sizeof(ULONGLONG));
  4656. pingEnum = midl_user_allocate(pingEnumSize);
  4657. if (pingEnum == NULL) {
  4658. ClRtlLogPrint(LOG_UNUSUAL,
  4659. "[NM] Failed to allocate memory for ping list.\n"
  4660. );
  4661. status = ERROR_NOT_ENOUGH_MEMORY;
  4662. goto error_exit;
  4663. }
  4664. pingEnum->AddressSize = sizeof(ULONG);
  4665. pingEnum->AddressCount = 0;
  4666. //
  4667. // Fetch the IP Route Table
  4668. //
  4669. allocSize = sizeof(MIB_IPFORWARDTABLE) + (sizeof(MIB_IPFORWARDROW) * 20);
  4670. do {
  4671. if (ipForwardTable != NULL) {
  4672. LocalFree(ipForwardTable);
  4673. }
  4674. ipForwardTable = LocalAlloc(LMEM_FIXED, allocSize);
  4675. if (ipForwardTable == NULL) {
  4676. ClRtlLogPrint(LOG_UNUSUAL,
  4677. "[NM] Failed to allocate memory for IP route table.\n"
  4678. );
  4679. status = ERROR_NOT_ENOUGH_MEMORY;
  4680. goto error_exit;
  4681. }
  4682. tableSize = allocSize;
  4683. status = GetIpForwardTable(
  4684. ipForwardTable,
  4685. &tableSize,
  4686. FALSE
  4687. );
  4688. allocSize = tableSize;
  4689. } while (status == ERROR_INSUFFICIENT_BUFFER);
  4690. if (status != ERROR_SUCCESS) {
  4691. ClRtlLogPrint(LOG_UNUSUAL,
  4692. "[ClNet] Failed to obtain IP route table, status %1!u!.\n",
  4693. status
  4694. );
  4695. goto error_exit;
  4696. }
  4697. //
  4698. // Add the IP route entries to the ping list.
  4699. //
  4700. for ( ipRow = &(ipForwardTable->table[0]),
  4701. ipRowLimit = ipRow + ipForwardTable->dwNumEntries;
  4702. ipRow < ipRowLimit;
  4703. ipRow++
  4704. )
  4705. {
  4706. if ((ipRow->dwForwardNextHop & netMask) == netAddress) {
  4707. //
  4708. // Make sure this address isn't in the online address enum.
  4709. //
  4710. duplicate = NmpIsAddressInAddressEnum(
  4711. (ULONGLONG) ipRow->dwForwardNextHop,
  4712. OnlineAddressEnum
  4713. );
  4714. if (!duplicate) {
  4715. //
  4716. // Make sure this address isn't already in the ping enum.
  4717. //
  4718. duplicate = NmpIsAddressInAddressEnum(
  4719. (ULONGLONG) ipRow->dwForwardNextHop,
  4720. pingEnum
  4721. );
  4722. if (!duplicate) {
  4723. pingEnum->AddressList[pingEnum->AddressCount++] =
  4724. (ULONGLONG) ipRow->dwForwardNextHop;
  4725. if (pingEnum->AddressCount == NM_MAX_IF_PING_ENUM_SIZE) {
  4726. LocalFree(ipForwardTable);
  4727. *PingAddressEnum = pingEnum;
  4728. NmpAcquireLock();
  4729. return(ERROR_SUCCESS);
  4730. }
  4731. }
  4732. }
  4733. }
  4734. }
  4735. LocalFree(ipForwardTable); ipForwardTable = NULL;
  4736. //
  4737. // Fetch the TCP Connection Table
  4738. //
  4739. allocSize = sizeof(MIB_TCPTABLE) + (sizeof(MIB_TCPROW) * 20);
  4740. do {
  4741. if (tcpTable != NULL) {
  4742. LocalFree(tcpTable);
  4743. }
  4744. tcpTable = LocalAlloc(LMEM_FIXED, allocSize);
  4745. if (tcpTable == NULL) {
  4746. ClRtlLogPrint(LOG_UNUSUAL,
  4747. "[NM] Failed to allocate memory for TCP conn table.\n"
  4748. );
  4749. status = ERROR_NOT_ENOUGH_MEMORY;
  4750. goto error_exit;
  4751. }
  4752. tableSize = allocSize;
  4753. status = GetTcpTable(
  4754. tcpTable,
  4755. &tableSize,
  4756. FALSE
  4757. );
  4758. allocSize = tableSize;
  4759. } while (status == ERROR_INSUFFICIENT_BUFFER);
  4760. if (status != ERROR_SUCCESS) {
  4761. ClRtlLogPrint(LOG_UNUSUAL,
  4762. "[ClNet] Failed to obtain TCP conn table, status %1!u!.\n",
  4763. status
  4764. );
  4765. goto error_exit;
  4766. }
  4767. //
  4768. // Add the TCP remote addresses to the ping list.
  4769. //
  4770. for ( tcpRow = &(tcpTable->table[0]),
  4771. tcpRowLimit = tcpRow + tcpTable->dwNumEntries;
  4772. tcpRow < tcpRowLimit;
  4773. tcpRow++
  4774. )
  4775. {
  4776. if ((tcpRow->dwRemoteAddr & netMask) == netAddress) {
  4777. //
  4778. // Make sure this address isn't in the online address enum.
  4779. //
  4780. duplicate = NmpIsAddressInAddressEnum(
  4781. (ULONGLONG) tcpRow->dwRemoteAddr,
  4782. OnlineAddressEnum
  4783. );
  4784. if (!duplicate) {
  4785. //
  4786. // Make sure this address isn't already in the ping enum.
  4787. //
  4788. duplicate = NmpIsAddressInAddressEnum(
  4789. (ULONGLONG) tcpRow->dwRemoteAddr,
  4790. pingEnum
  4791. );
  4792. if (!duplicate) {
  4793. pingEnum->AddressList[pingEnum->AddressCount++] =
  4794. (ULONGLONG) tcpRow->dwRemoteAddr;
  4795. if (pingEnum->AddressCount == NM_MAX_IF_PING_ENUM_SIZE) {
  4796. break;
  4797. }
  4798. }
  4799. }
  4800. }
  4801. }
  4802. *PingAddressEnum = pingEnum; pingEnum = NULL;
  4803. error_exit:
  4804. if (pingEnum != NULL) {
  4805. midl_user_free(pingEnum);
  4806. }
  4807. if (ipForwardTable != NULL) {
  4808. LocalFree(ipForwardTable);
  4809. }
  4810. if (tcpTable != NULL) {
  4811. LocalFree(tcpTable);
  4812. }
  4813. NmpAcquireLock();
  4814. return(status);
  4815. } // NmpBuildInterfacePingAddressEnum
  4816. NmpGetInterfaceOnlineAddressEnum(
  4817. PNM_INTERFACE Interface,
  4818. PNM_ADDRESS_ENUM * OnlineAddressEnum
  4819. )
  4820. /*++
  4821. Notes:
  4822. Called with NmpLock held and Interface referenced. Releases and
  4823. reacquires NmpLock.
  4824. --*/
  4825. {
  4826. DWORD status;
  4827. LPCWSTR interfaceId = OmObjectId(Interface);
  4828. PNM_NODE node = Interface->Node;
  4829. RPC_BINDING_HANDLE rpcBinding = node->IsolateRpcBinding;
  4830. if (node == NmLocalNode) {
  4831. //
  4832. // Call the internal routine directly
  4833. //
  4834. status = NmpBuildInterfaceOnlineAddressEnum(
  4835. Interface,
  4836. OnlineAddressEnum
  4837. );
  4838. }
  4839. else {
  4840. OmReferenceObject(node);
  4841. NmpReleaseLock();
  4842. CL_ASSERT(rpcBinding != NULL);
  4843. NmStartRpc(node->NodeId);
  4844. status = NmRpcGetInterfaceOnlineAddressEnum(
  4845. rpcBinding,
  4846. (LPWSTR) interfaceId,
  4847. OnlineAddressEnum
  4848. );
  4849. NmEndRpc(node->NodeId);
  4850. if(status != RPC_S_OK) {
  4851. NmDumpRpcExtErrorInfo(status);
  4852. }
  4853. NmpAcquireLock();
  4854. OmDereferenceObject(node);
  4855. }
  4856. if (status == ERROR_SUCCESS) {
  4857. if ((*OnlineAddressEnum)->AddressSize != sizeof(ULONG)) {
  4858. ClRtlLogPrint(LOG_UNUSUAL,
  4859. "[NM] Online enum address size is invalid for interface %1!ws!\n",
  4860. interfaceId
  4861. );
  4862. status = ERROR_INCORRECT_ADDRESS;
  4863. midl_user_free(*OnlineAddressEnum);
  4864. *OnlineAddressEnum = NULL;
  4865. }
  4866. else {
  4867. ClRtlLogPrint(LOG_NOISE,
  4868. "[NM] Online enum for interface %1!ws! contains %2!u! addresses\n",
  4869. interfaceId,
  4870. (*OnlineAddressEnum)->AddressCount
  4871. );
  4872. }
  4873. }
  4874. else {
  4875. ClRtlLogPrint(LOG_UNUSUAL,
  4876. "[NM] Failed to get online address enum for interface %1!ws!, status %2!u!\n",
  4877. interfaceId,
  4878. status
  4879. );
  4880. }
  4881. return(status);
  4882. } // NmpGetInterfaceOnlineAddressEnum
  4883. NmpGetInterfacePingAddressEnum(
  4884. PNM_INTERFACE Interface,
  4885. PNM_ADDRESS_ENUM OnlineAddressEnum,
  4886. PNM_ADDRESS_ENUM * PingAddressEnum
  4887. )
  4888. /*++
  4889. Notes:
  4890. Called with NmpLock held and Interface referenced. Releases and
  4891. reacquires NmpLock.
  4892. --*/
  4893. {
  4894. DWORD status;
  4895. LPCWSTR interfaceId = OmObjectId(Interface);
  4896. PNM_NODE node = Interface->Node;
  4897. RPC_BINDING_HANDLE rpcBinding = node->IsolateRpcBinding;
  4898. if (node == NmLocalNode) {
  4899. //
  4900. // Call the internal routine directly
  4901. //
  4902. status = NmpBuildInterfacePingAddressEnum(
  4903. Interface,
  4904. OnlineAddressEnum,
  4905. PingAddressEnum
  4906. );
  4907. }
  4908. else {
  4909. OmReferenceObject(node);
  4910. NmpReleaseLock();
  4911. CL_ASSERT(rpcBinding != NULL);
  4912. NmStartRpc(node->NodeId);
  4913. status = NmRpcGetInterfacePingAddressEnum(
  4914. rpcBinding,
  4915. (LPWSTR) interfaceId,
  4916. OnlineAddressEnum,
  4917. PingAddressEnum
  4918. );
  4919. NmEndRpc(node->NodeId);
  4920. if(status != RPC_S_OK) {
  4921. NmDumpRpcExtErrorInfo(status);
  4922. }
  4923. NmpAcquireLock();
  4924. OmDereferenceObject(node);
  4925. }
  4926. if (status == ERROR_SUCCESS) {
  4927. if ((*PingAddressEnum)->AddressSize != sizeof(ULONG)) {
  4928. ClRtlLogPrint(LOG_UNUSUAL,
  4929. "[NM] Ping enum address size is invalid for interface %1!ws!\n",
  4930. interfaceId
  4931. );
  4932. status = ERROR_INCORRECT_ADDRESS;
  4933. midl_user_free(*PingAddressEnum);
  4934. *PingAddressEnum = NULL;
  4935. }
  4936. else {
  4937. ClRtlLogPrint(LOG_NOISE,
  4938. "[NM] Ping enum for interface %1!ws! contains %2!u! addresses\n",
  4939. interfaceId,
  4940. (*PingAddressEnum)->AddressCount
  4941. );
  4942. }
  4943. }
  4944. else {
  4945. ClRtlLogPrint(LOG_UNUSUAL,
  4946. "[NM] Failed to get ping address enum for interface %1!ws!, status %2!u!\n",
  4947. interfaceId,
  4948. status
  4949. );
  4950. }
  4951. return(status);
  4952. } // NmpGetInterfacePingAddressEnum
  4953. DWORD
  4954. NmpDoInterfacePing(
  4955. IN PNM_INTERFACE Interface,
  4956. IN PNM_ADDRESS_ENUM PingAddressEnum,
  4957. OUT BOOLEAN * PingSucceeded
  4958. )
  4959. /*++
  4960. Notes:
  4961. Called with Interface referenced.
  4962. --*/
  4963. {
  4964. DWORD status = ERROR_SUCCESS;
  4965. LPCWSTR interfaceId = OmObjectId(Interface);
  4966. LPWSTR addressString;
  4967. DWORD maxAddressStringLength;
  4968. DWORD i;
  4969. ClRtlLogPrint(LOG_NOISE,
  4970. "[NM] Pinging targets for interface %1!ws!.\n",
  4971. interfaceId
  4972. );
  4973. *PingSucceeded = FALSE;
  4974. if (PingAddressEnum->AddressSize != sizeof(ULONG)) {
  4975. return(ERROR_INCORRECT_ADDRESS);
  4976. }
  4977. ClRtlQueryTcpipInformation(
  4978. &maxAddressStringLength,
  4979. NULL,
  4980. NULL
  4981. );
  4982. addressString = LocalAlloc(
  4983. LMEM_FIXED,
  4984. (maxAddressStringLength + 1) * sizeof(WCHAR)
  4985. );
  4986. if (addressString == NULL) {
  4987. ClRtlLogPrint(LOG_UNUSUAL,
  4988. "[NM] Failed to allocate memory for address string.\n"
  4989. );
  4990. return(ERROR_NOT_ENOUGH_MEMORY);
  4991. }
  4992. for (i=0; i<PingAddressEnum->AddressCount; i++) {
  4993. status = ClRtlTcpipAddressToString(
  4994. (ULONG) PingAddressEnum->AddressList[i],
  4995. &addressString
  4996. );
  4997. if (status == ERROR_SUCCESS) {
  4998. ClRtlLogPrint(LOG_NOISE,
  4999. "[NM] Pinging host %1!ws!\n",
  5000. addressString
  5001. );
  5002. }
  5003. else {
  5004. ClRtlLogPrint(LOG_UNUSUAL,
  5005. "[NM] Failed to convert address %1!x! to string %2!u!.\n",
  5006. (ULONG) PingAddressEnum->AddressList[i],
  5007. status
  5008. );
  5009. }
  5010. if ( ClRtlIsDuplicateTcpipAddress(
  5011. (ULONG) PingAddressEnum->AddressList[i])
  5012. )
  5013. {
  5014. ClRtlLogPrint(LOG_NOISE,
  5015. "[NM] Ping of host %1!ws! succeeded.\n",
  5016. addressString
  5017. );
  5018. *PingSucceeded = TRUE;
  5019. break;
  5020. }
  5021. else {
  5022. ClRtlLogPrint(LOG_NOISE,
  5023. "[NM] Ping of host %1!ws! failed.\n",
  5024. addressString
  5025. );
  5026. }
  5027. }
  5028. LocalFree(addressString);
  5029. return(status);
  5030. } // NmpDoInterfacePing
  5031. DWORD
  5032. NmpTestInterfaceConnectivity(
  5033. PNM_INTERFACE Interface1,
  5034. PBOOLEAN Interface1HasConnectivity,
  5035. PNM_INTERFACE Interface2,
  5036. PBOOLEAN Interface2HasConnectivity
  5037. )
  5038. /*++
  5039. Notes:
  5040. Called with NmpLock held. This routine releases and reacquires the
  5041. NmpLock. It must be called with references on the target interfaces.
  5042. --*/
  5043. {
  5044. DWORD status, status1, status2;
  5045. PNM_NETWORK network = Interface1->Network;
  5046. PNM_INTERFACE localInterface = network->LocalInterface;
  5047. LPCWSTR networkId = OmObjectId(network);
  5048. LPCWSTR interface1Id = OmObjectId(Interface1);
  5049. LPCWSTR interface2Id = OmObjectId(Interface2);
  5050. ULONG interface1Address, interface2Address;
  5051. PNM_ADDRESS_ENUM pingEnum1 = NULL, pingEnum2 = NULL;
  5052. PNM_ADDRESS_ENUM onlineEnum1 = NULL, onlineEnum2 = NULL;
  5053. PNM_ADDRESS_ENUM unionPingEnum = NULL, unionOnlineEnum = NULL;
  5054. DWORD addressCount;
  5055. RPC_ASYNC_STATE async1, async2;
  5056. HANDLE event1 = NULL, event2 = NULL;
  5057. RPC_BINDING_HANDLE rpcBinding1 = NULL, rpcBinding2 = NULL;
  5058. DWORD i1, i2;
  5059. BOOL duplicate;
  5060. //
  5061. // Reference the nodes associated with the target interfaces so they
  5062. // can't go away during this process.
  5063. //
  5064. OmReferenceObject(Interface1->Node);
  5065. OmReferenceObject(Interface2->Node);
  5066. if (localInterface != NULL) {
  5067. OmReferenceObject(localInterface);
  5068. }
  5069. *Interface1HasConnectivity = *Interface2HasConnectivity = FALSE;
  5070. //
  5071. // Convert the interface address strings to binary form.
  5072. //
  5073. status = ClRtlTcpipStringToAddress(
  5074. Interface1->Address,
  5075. &interface1Address
  5076. );
  5077. if (status != ERROR_SUCCESS) {
  5078. ClRtlLogPrint(LOG_UNUSUAL,
  5079. "[NM] Failed to convert interface address string %1!ws! to binary, status %2!u!.\n",
  5080. Interface1->Address,
  5081. status
  5082. );
  5083. goto error_exit;
  5084. }
  5085. status = ClRtlTcpipStringToAddress(
  5086. Interface2->Address,
  5087. &interface2Address
  5088. );
  5089. if (status != ERROR_SUCCESS) {
  5090. ClRtlLogPrint(LOG_UNUSUAL,
  5091. "[NM] Failed to convert interface address string %1!ws! to binary, status %2!u!.\n",
  5092. Interface2->Address,
  5093. status
  5094. );
  5095. goto error_exit;
  5096. }
  5097. //
  5098. // Fetch the online address list from each of the interfaces.
  5099. // The NmpLock will be released when querying a remote interface.
  5100. //
  5101. status = NmpGetInterfaceOnlineAddressEnum(
  5102. Interface1,
  5103. &onlineEnum1
  5104. );
  5105. if (status != ERROR_SUCCESS) {
  5106. goto error_exit;
  5107. }
  5108. status = NmpGetInterfaceOnlineAddressEnum(
  5109. Interface2,
  5110. &onlineEnum2
  5111. );
  5112. if (status != ERROR_SUCCESS) {
  5113. goto error_exit;
  5114. }
  5115. //
  5116. // Bail out if either of the interfaces was deleted while the NmpLock
  5117. // was released.
  5118. //
  5119. if ((NM_DELETE_PENDING(Interface1) || NM_DELETE_PENDING(Interface2))) {
  5120. ClRtlLogPrint(LOG_NOISE,
  5121. "[NM] Aborting interface connectivity test on network %1!ws! "
  5122. "because an interface was deleted.\n",
  5123. networkId
  5124. );
  5125. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  5126. goto error_exit;
  5127. }
  5128. //
  5129. // Take the union of the two online lists
  5130. //
  5131. addressCount = onlineEnum1->AddressCount + onlineEnum2->AddressCount;
  5132. ClRtlLogPrint(LOG_NOISE,
  5133. "[NM] Total online address count for network %1!ws! is %2!u!\n",
  5134. networkId,
  5135. addressCount
  5136. );
  5137. if (addressCount == 0) {
  5138. unionOnlineEnum = LocalAlloc(LMEM_FIXED, sizeof(NM_ADDRESS_ENUM));
  5139. }
  5140. else {
  5141. unionOnlineEnum = LocalAlloc(
  5142. LMEM_FIXED,
  5143. sizeof(NM_ADDRESS_ENUM) +
  5144. ((addressCount - 1) * sizeof(ULONGLONG))
  5145. );
  5146. }
  5147. if (unionOnlineEnum == NULL) {
  5148. ClRtlLogPrint(LOG_UNUSUAL,
  5149. "[NM] Failed to allocate memory for union ping list.\n"
  5150. );
  5151. status = ERROR_NOT_ENOUGH_MEMORY;
  5152. goto error_exit;
  5153. }
  5154. unionOnlineEnum->AddressSize = sizeof(ULONG);
  5155. unionOnlineEnum->AddressCount = 0;
  5156. if (onlineEnum1->AddressCount != 0) {
  5157. CopyMemory(
  5158. &(unionOnlineEnum->AddressList[0]),
  5159. &(onlineEnum1->AddressList[0]),
  5160. onlineEnum1->AddressCount * sizeof(ULONGLONG)
  5161. );
  5162. unionOnlineEnum->AddressCount = onlineEnum1->AddressCount;
  5163. }
  5164. if (onlineEnum2->AddressCount != 0) {
  5165. CopyMemory(
  5166. &(unionOnlineEnum->AddressList[unionOnlineEnum->AddressCount]),
  5167. &(onlineEnum2->AddressList[0]),
  5168. onlineEnum2->AddressCount * sizeof(ULONGLONG)
  5169. );
  5170. unionOnlineEnum->AddressCount += onlineEnum2->AddressCount;
  5171. }
  5172. midl_user_free(onlineEnum1); onlineEnum1 = NULL;
  5173. midl_user_free(onlineEnum2); onlineEnum2 = NULL;
  5174. //
  5175. // Fetch the ping target list from each of the interfaces.
  5176. // The NmpLock will be released when querying a remote interface.
  5177. //
  5178. status = NmpGetInterfacePingAddressEnum(
  5179. Interface1,
  5180. unionOnlineEnum,
  5181. &pingEnum1
  5182. );
  5183. if (status != ERROR_SUCCESS) {
  5184. goto error_exit;
  5185. }
  5186. status = NmpGetInterfacePingAddressEnum(
  5187. Interface2,
  5188. unionOnlineEnum,
  5189. &pingEnum2
  5190. );
  5191. if (status != ERROR_SUCCESS) {
  5192. goto error_exit;
  5193. }
  5194. //
  5195. // Bail out if either of the interfaces was deleted while the NmpLock
  5196. // was released.
  5197. //
  5198. if ((NM_DELETE_PENDING(Interface1) || NM_DELETE_PENDING(Interface2))) {
  5199. ClRtlLogPrint(LOG_NOISE,
  5200. "[NM] Aborting interface connectivity test on network %1!ws! "
  5201. "because an interface was deleted.\n",
  5202. networkId
  5203. );
  5204. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  5205. goto error_exit;
  5206. }
  5207. NmpReleaseLock();
  5208. //
  5209. // Take the union of the two ping lists
  5210. //
  5211. addressCount = pingEnum1->AddressCount + pingEnum2->AddressCount;
  5212. ClRtlLogPrint(LOG_NOISE,
  5213. "[NM] Total ping address count for network %1!ws! is %2!u!\n",
  5214. networkId,
  5215. addressCount
  5216. );
  5217. if (addressCount == 0) {
  5218. status = ERROR_SUCCESS;
  5219. goto error_lock_and_exit;
  5220. }
  5221. unionPingEnum = LocalAlloc(
  5222. LMEM_FIXED,
  5223. sizeof(NM_ADDRESS_ENUM) +
  5224. ( (NM_MAX_UNION_PING_ENUM_SIZE - 1) *
  5225. sizeof(ULONGLONG)
  5226. )
  5227. );
  5228. if (unionPingEnum == NULL) {
  5229. ClRtlLogPrint(LOG_UNUSUAL,
  5230. "[NM] Failed to allocate memory for union ping list.\n"
  5231. );
  5232. status = ERROR_NOT_ENOUGH_MEMORY;
  5233. goto error_lock_and_exit;
  5234. }
  5235. unionPingEnum->AddressSize = sizeof(ULONG);
  5236. unionPingEnum->AddressCount = 0;
  5237. i1 = 0; i2 = 0;
  5238. while (TRUE) {
  5239. while (i1 < pingEnum1->AddressCount) {
  5240. duplicate = NmpIsAddressInAddressEnum(
  5241. pingEnum1->AddressList[i1],
  5242. unionPingEnum
  5243. );
  5244. if (!duplicate) {
  5245. unionPingEnum->AddressList[unionPingEnum->AddressCount++] =
  5246. pingEnum1->AddressList[i1++];
  5247. break;
  5248. }
  5249. else {
  5250. i1++;
  5251. }
  5252. }
  5253. if (unionPingEnum->AddressCount == NM_MAX_UNION_PING_ENUM_SIZE) {
  5254. break;
  5255. }
  5256. while (i2 < pingEnum2->AddressCount) {
  5257. duplicate = NmpIsAddressInAddressEnum(
  5258. pingEnum2->AddressList[i2],
  5259. unionPingEnum
  5260. );
  5261. if (!duplicate) {
  5262. unionPingEnum->AddressList[unionPingEnum->AddressCount++] =
  5263. pingEnum2->AddressList[i2++];
  5264. break;
  5265. }
  5266. else {
  5267. i2++;
  5268. }
  5269. }
  5270. if ( (unionPingEnum->AddressCount == NM_MAX_UNION_PING_ENUM_SIZE) ||
  5271. ( (i1 == pingEnum1->AddressCount) &&
  5272. (i2 == pingEnum2->AddressCount)
  5273. )
  5274. )
  5275. {
  5276. break;
  5277. }
  5278. }
  5279. midl_user_free(pingEnum1); pingEnum1 = NULL;
  5280. midl_user_free(pingEnum2); pingEnum2 = NULL;
  5281. ClRtlLogPrint(LOG_NOISE,
  5282. "[NM] Union ping list for network %1!ws! contains %2!u! addresses\n",
  5283. networkId,
  5284. unionPingEnum->AddressCount
  5285. );
  5286. //
  5287. // Ask each interface to ping the list of targets using async RPC calls
  5288. //
  5289. //
  5290. // Allocate resources for the async RPC calls
  5291. //
  5292. if (Interface1 != localInterface) {
  5293. event1 = CreateEvent(NULL, FALSE, FALSE, NULL);
  5294. if (event1 == NULL) {
  5295. status = GetLastError();
  5296. ClRtlLogPrint(LOG_UNUSUAL,
  5297. "[NM] Failed to allocate event for async rpc, status %1!u!.\n",
  5298. status
  5299. );
  5300. goto error_lock_and_exit;
  5301. }
  5302. status = RpcAsyncInitializeHandle(&async1, sizeof(async1));
  5303. if (status != RPC_S_OK) {
  5304. ClRtlLogPrint(LOG_UNUSUAL,
  5305. "[NM] Failed to initialize RPC async state, status %1!u!.\n",
  5306. status
  5307. );
  5308. goto error_lock_and_exit;
  5309. }
  5310. async1.NotificationType = RpcNotificationTypeEvent;
  5311. async1.u.hEvent = event1;
  5312. rpcBinding1 = Interface1->Node->IsolateRpcBinding;
  5313. }
  5314. if (Interface2 != localInterface) {
  5315. event2 = CreateEvent(NULL, FALSE, FALSE, NULL);
  5316. if (event2 == NULL) {
  5317. status = GetLastError();
  5318. ClRtlLogPrint(LOG_UNUSUAL,
  5319. "[NM] Failed to allocate event for async rpc, status %1!u!.\n",
  5320. status
  5321. );
  5322. goto error_lock_and_exit;
  5323. }
  5324. status = RpcAsyncInitializeHandle(&async2, sizeof(async2));
  5325. if (status != RPC_S_OK) {
  5326. ClRtlLogPrint(LOG_UNUSUAL,
  5327. "[NM] Failed to initialize RPC async state, status %1!u!.\n",
  5328. status
  5329. );
  5330. goto error_lock_and_exit;
  5331. }
  5332. async2.NotificationType = RpcNotificationTypeEvent;
  5333. async2.u.hEvent = event2;
  5334. rpcBinding2 = Interface2->Node->IsolateRpcBinding;
  5335. }
  5336. if (rpcBinding1 != NULL) {
  5337. //
  5338. // Issue the RPC for interface1 first. Then deal with interface2
  5339. //
  5340. //
  5341. // We need the try-except until a bug is fixed in MIDL
  5342. //
  5343. ClRtlLogPrint(LOG_NOISE,
  5344. "[NM] Issuing RpcDoInterfacePing for interface %1!ws!\n",
  5345. interface1Id
  5346. );
  5347. status = ERROR_SUCCESS;
  5348. try {
  5349. NmRpcDoInterfacePing(
  5350. &async1,
  5351. rpcBinding1,
  5352. (LPWSTR) interface1Id,
  5353. unionPingEnum,
  5354. Interface1HasConnectivity,
  5355. &status1
  5356. );
  5357. } except(I_RpcExceptionFilter(RpcExceptionCode())) {
  5358. status = GetExceptionCode();
  5359. }
  5360. if (status != ERROR_SUCCESS) {
  5361. ClRtlLogPrint(LOG_UNUSUAL,
  5362. "[NM] DoPing RPC failed for interface %1!ws!, status %2!u!.\n",
  5363. interface1Id,
  5364. status
  5365. );
  5366. goto error_lock_and_exit;
  5367. }
  5368. if (rpcBinding2 != NULL) {
  5369. //
  5370. // Issue the RPC for interface2.
  5371. //
  5372. ClRtlLogPrint(LOG_NOISE,
  5373. "[NM] Issuing RpcDoInterfacePing for interface %1!ws!\n",
  5374. interface2Id
  5375. );
  5376. status = ERROR_SUCCESS;
  5377. try {
  5378. NmRpcDoInterfacePing(
  5379. &async2,
  5380. rpcBinding2,
  5381. (LPWSTR) interface2Id,
  5382. unionPingEnum,
  5383. Interface2HasConnectivity,
  5384. &status2
  5385. );
  5386. } except(I_RpcExceptionFilter(RpcExceptionCode())) {
  5387. status = GetExceptionCode();
  5388. }
  5389. if (status != ERROR_SUCCESS) {
  5390. ClRtlLogPrint(LOG_UNUSUAL,
  5391. "[NM] DoPing RPC failed for interface %1!ws!, status %2!u!.\n",
  5392. interface1Id,
  5393. status
  5394. );
  5395. goto error_lock_and_exit;
  5396. }
  5397. //
  5398. // Wait for the RPC for interface2 to complete
  5399. //
  5400. ClRtlLogPrint(LOG_NOISE,
  5401. "[NM] Waiting for RpcDoInterfacePing for interface %1!ws! to complete\n",
  5402. interface2Id
  5403. );
  5404. status = WaitForSingleObjectEx(event2, INFINITE, FALSE);
  5405. CL_ASSERT(status == WAIT_OBJECT_0);
  5406. status = RpcAsyncCompleteCall(
  5407. &async2,
  5408. &status2
  5409. );
  5410. CL_ASSERT(status == RPC_S_OK);
  5411. ClRtlLogPrint(LOG_NOISE,
  5412. "[NM] Wait for RpcDoInterfacePing for interface %1!ws! completed.\n",
  5413. interface2Id
  5414. );
  5415. }
  5416. else {
  5417. //
  5418. // Call the local routine for interface2.
  5419. //
  5420. status2 = NmpDoInterfacePing(
  5421. Interface2,
  5422. unionPingEnum,
  5423. Interface2HasConnectivity
  5424. );
  5425. }
  5426. //
  5427. // Wait for the RPC for interface1 to complete
  5428. //
  5429. ClRtlLogPrint(LOG_NOISE,
  5430. "[NM] Waiting for RpcDoInterfacePing for interface %1!ws! to complete\n",
  5431. interface1Id
  5432. );
  5433. status = WaitForSingleObjectEx(event1, INFINITE, FALSE);
  5434. CL_ASSERT(status == WAIT_OBJECT_0);
  5435. status = RpcAsyncCompleteCall(
  5436. &async1,
  5437. &status1
  5438. );
  5439. CL_ASSERT(status == RPC_S_OK);
  5440. ClRtlLogPrint(LOG_NOISE,
  5441. "[NM] Wait for RpcDoInterfacePing for interface %1!ws! completed.\n",
  5442. interface1Id
  5443. );
  5444. }
  5445. else {
  5446. //
  5447. // Send the RPC to interface2 first. Then call the local
  5448. // routine for interface1
  5449. //
  5450. CL_ASSERT(rpcBinding2 != NULL);
  5451. ClRtlLogPrint(LOG_NOISE,
  5452. "[NM] Issuing RpcDoInterfacePing for interface %1!ws!\n",
  5453. interface2Id
  5454. );
  5455. status = ERROR_SUCCESS;
  5456. try {
  5457. NmRpcDoInterfacePing(
  5458. &async2,
  5459. rpcBinding2,
  5460. (LPWSTR) interface2Id,
  5461. unionPingEnum,
  5462. Interface2HasConnectivity,
  5463. &status2
  5464. );
  5465. } except(I_RpcExceptionFilter(RpcExceptionCode())) {
  5466. status = GetExceptionCode();
  5467. }
  5468. if (status != ERROR_SUCCESS) {
  5469. ClRtlLogPrint(LOG_UNUSUAL,
  5470. "[NM] DoPing RPC failed for interface %1!ws!, status %2!u!.\n",
  5471. interface1Id,
  5472. status
  5473. );
  5474. goto error_lock_and_exit;
  5475. }
  5476. status1 = NmpDoInterfacePing(
  5477. Interface1,
  5478. unionPingEnum,
  5479. Interface1HasConnectivity
  5480. );
  5481. //
  5482. // Wait for the RPC for interface2 to complete
  5483. //
  5484. ClRtlLogPrint(LOG_NOISE,
  5485. "[NM] Waiting for RpcDoInterfacePing for interface %1!ws! to complete\n",
  5486. interface2Id
  5487. );
  5488. status = WaitForSingleObject(event2, INFINITE);
  5489. CL_ASSERT(status == WAIT_OBJECT_0);
  5490. status = RpcAsyncCompleteCall(
  5491. &async2,
  5492. &status2
  5493. );
  5494. CL_ASSERT(status == RPC_S_OK);
  5495. ClRtlLogPrint(LOG_NOISE,
  5496. "[NM] Wait for RpcDoInterfacePing for interface %1!ws! completed.\n",
  5497. interface2Id
  5498. );
  5499. }
  5500. if (status1 != RPC_S_OK) {
  5501. status = status1;
  5502. ClRtlLogPrint(LOG_UNUSUAL,
  5503. "[NM] DoPing RPC failed for interface %1!ws!, status %2!u!.\n",
  5504. interface1Id,
  5505. status
  5506. );
  5507. goto error_lock_and_exit;
  5508. }
  5509. if (status2 != RPC_S_OK) {
  5510. status = status2;
  5511. ClRtlLogPrint(LOG_UNUSUAL,
  5512. "[NM] DoPing RPC failed for interface %1!ws!, status %2!u!.\n",
  5513. interface2Id,
  5514. status
  5515. );
  5516. goto error_lock_and_exit;
  5517. }
  5518. error_lock_and_exit:
  5519. NmpAcquireLock();
  5520. if ( (status == ERROR_SUCCESS) &&
  5521. (NM_DELETE_PENDING(Interface1) || NM_DELETE_PENDING(Interface2))
  5522. )
  5523. {
  5524. ClRtlLogPrint(LOG_NOISE,
  5525. "[NM] Aborting interface connectivity test on network %1!ws! "
  5526. "because an interface was deleted.\n",
  5527. networkId
  5528. );
  5529. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  5530. }
  5531. error_exit:
  5532. OmDereferenceObject(Interface1->Node);
  5533. OmDereferenceObject(Interface2->Node);
  5534. if (localInterface != NULL) {
  5535. OmDereferenceObject(localInterface);
  5536. }
  5537. if (onlineEnum1 != NULL) {
  5538. midl_user_free(onlineEnum1);
  5539. }
  5540. if (onlineEnum2 != NULL) {
  5541. midl_user_free(onlineEnum2);
  5542. }
  5543. if (unionOnlineEnum != NULL) {
  5544. LocalFree(unionOnlineEnum);
  5545. }
  5546. if (pingEnum1 != NULL) {
  5547. midl_user_free(pingEnum1);
  5548. }
  5549. if (pingEnum2 != NULL) {
  5550. midl_user_free(pingEnum2);
  5551. }
  5552. if (unionPingEnum != NULL) {
  5553. LocalFree(unionPingEnum);
  5554. }
  5555. if (event1 != NULL) {
  5556. CloseHandle(event1);
  5557. }
  5558. if (event2 != NULL) {
  5559. CloseHandle(event2);
  5560. }
  5561. return(status);
  5562. } // NmpTestInterfaceConnectivity
  5563. /////////////////////////////////////////////////////////////////////////////
  5564. //
  5565. // Miscellaneous routines
  5566. //
  5567. /////////////////////////////////////////////////////////////////////////////
  5568. DWORD
  5569. NmpRegisterInterface(
  5570. IN PNM_INTERFACE Interface,
  5571. IN BOOLEAN RetryOnFailure
  5572. )
  5573. /*++
  5574. Called with the NmpLock held.
  5575. --*/
  5576. {
  5577. DWORD status;
  5578. LPWSTR interfaceId = (LPWSTR) OmObjectId(Interface);
  5579. PNM_NETWORK network = Interface->Network;
  5580. PVOID tdiAddress = NULL;
  5581. ULONG tdiAddressLength = 0;
  5582. NDIS_MEDIA_STATE mediaStatus;
  5583. CL_ASSERT(!NmpIsInterfaceRegistered(Interface));
  5584. ClRtlLogPrint(LOG_NOISE,
  5585. "[NM] Registering interface %1!ws! (%2!ws!) with cluster transport, "
  5586. "addr %3!ws!, endpoint %4!ws!.\n",
  5587. interfaceId,
  5588. OmObjectName(Interface),
  5589. Interface->Address,
  5590. Interface->ClusnetEndpoint
  5591. );
  5592. status = ClRtlBuildTcpipTdiAddress(
  5593. Interface->Address,
  5594. Interface->ClusnetEndpoint,
  5595. &tdiAddress,
  5596. &tdiAddressLength
  5597. );
  5598. if (status == ERROR_SUCCESS) {
  5599. status = ClusnetRegisterInterface(
  5600. NmClusnetHandle,
  5601. Interface->Node->NodeId,
  5602. Interface->Network->ShortId,
  5603. 0,
  5604. Interface->AdapterId,
  5605. wcslen(Interface->AdapterId) * sizeof(WCHAR),
  5606. tdiAddress,
  5607. tdiAddressLength,
  5608. (PULONG) &mediaStatus
  5609. );
  5610. LocalFree(tdiAddress);
  5611. if (status == ERROR_SUCCESS) {
  5612. Interface->Flags |= NM_FLAG_IF_REGISTERED;
  5613. network->RegistrationRetryTimeout = 0;
  5614. //
  5615. // If this is a local interface, and if its media status
  5616. // indicates that it is connected, schedule a worker thread to
  5617. // deliver an interface up notification. Clusnet does not
  5618. // deliver interface up events for local interfaces.
  5619. //
  5620. if (network->LocalInterface == Interface) {
  5621. if (mediaStatus == NdisMediaStateConnected) {
  5622. network->Flags |= NM_FLAG_NET_REPORT_LOCAL_IF_UP;
  5623. NmpScheduleNetworkConnectivityReport(network);
  5624. } else {
  5625. ClRtlLogPrint(LOG_UNUSUAL,
  5626. "[NM] Local interface %1!ws! reported "
  5627. "disconnected.\n",
  5628. interfaceId,
  5629. status
  5630. );
  5631. network->Flags |= NM_FLAG_NET_REPORT_LOCAL_IF_FAILED;
  5632. NmpScheduleNetworkConnectivityReport(network);
  5633. }
  5634. }
  5635. }
  5636. else {
  5637. ClRtlLogPrint(LOG_CRITICAL,
  5638. "[NM] Failed to register interface %1!ws! with cluster "
  5639. "transport, status %2!u!.\n",
  5640. interfaceId,
  5641. status
  5642. );
  5643. }
  5644. }
  5645. else {
  5646. ClRtlLogPrint(LOG_CRITICAL,
  5647. "[NM] Failed to build TDI bind address for interface %1!ws!, "
  5648. "status %2!u!.\n",
  5649. interfaceId,
  5650. status
  5651. );
  5652. }
  5653. if (status != ERROR_SUCCESS) {
  5654. WCHAR string[16];
  5655. wsprintfW(&(string[0]), L"%u", status);
  5656. CsLogEvent3(
  5657. LOG_UNUSUAL,
  5658. NM_EVENT_REGISTER_NETINTERFACE_FAILED,
  5659. OmObjectName(Interface->Node),
  5660. OmObjectName(Interface->Network),
  5661. string
  5662. );
  5663. //
  5664. // Retry if the error is transient
  5665. //
  5666. if ( RetryOnFailure &&
  5667. ( (status == ERROR_INVALID_NETNAME) ||
  5668. (status == ERROR_NOT_ENOUGH_MEMORY) ||
  5669. (status == ERROR_NO_SYSTEM_RESOURCES)
  5670. )
  5671. )
  5672. {
  5673. NmpStartNetworkRegistrationRetryTimer(network);
  5674. status = ERROR_SUCCESS;
  5675. }
  5676. }
  5677. return(status);
  5678. } // NmpRegisterInterface
  5679. VOID
  5680. NmpDeregisterInterface(
  5681. IN PNM_INTERFACE Interface
  5682. )
  5683. /*++
  5684. Routine Description:
  5685. Deregisters an interface from the cluster transport.
  5686. Arguments:
  5687. Interface - A pointer to the interface to deregister.
  5688. Return Value:
  5689. None.
  5690. Notes:
  5691. Called with the NmpLock held.
  5692. --*/
  5693. {
  5694. DWORD status;
  5695. CL_ASSERT(NmpIsInterfaceRegistered(Interface));
  5696. ClRtlLogPrint(LOG_NOISE,
  5697. "[NM] Deregistering interface %1!ws! (%2!ws!) from cluster "
  5698. "transport.\n",
  5699. OmObjectId(Interface),
  5700. OmObjectName(Interface)
  5701. );
  5702. status = ClusnetDeregisterInterface(
  5703. NmClusnetHandle,
  5704. Interface->Node->NodeId,
  5705. Interface->Network->ShortId
  5706. );
  5707. CL_ASSERT(
  5708. (status == ERROR_SUCCESS) ||
  5709. (status == ERROR_CLUSTER_NETINTERFACE_NOT_FOUND)
  5710. );
  5711. Interface->Flags &= ~NM_FLAG_IF_REGISTERED;
  5712. return;
  5713. } // NmpDeregisterNetwork
  5714. DWORD
  5715. NmpPrepareToCreateInterface(
  5716. IN PNM_INTERFACE_INFO2 InterfaceInfo,
  5717. OUT PNM_NETWORK * Network,
  5718. OUT PNM_NODE * Node
  5719. )
  5720. {
  5721. DWORD status;
  5722. PNM_INTERFACE netInterface = NULL;
  5723. PNM_NODE node = NULL;
  5724. PNM_NETWORK network = NULL;
  5725. PLIST_ENTRY entry;
  5726. *Node = NULL;
  5727. *Network = NULL;
  5728. //
  5729. // Verify that the associated node and network objects exist.
  5730. //
  5731. network = OmReferenceObjectById(
  5732. ObjectTypeNetwork,
  5733. InterfaceInfo->NetworkId
  5734. );
  5735. if (network == NULL) {
  5736. status = ERROR_CLUSTER_NETWORK_NOT_FOUND;
  5737. ClRtlLogPrint(LOG_CRITICAL,
  5738. "[NM] Network %1!ws! does not exist. Cannot create "
  5739. "interface %2!ws!\n",
  5740. InterfaceInfo->NetworkId,
  5741. InterfaceInfo->Id
  5742. );
  5743. goto error_exit;
  5744. }
  5745. node = OmReferenceObjectById(ObjectTypeNode, InterfaceInfo->NodeId);
  5746. if (node == NULL) {
  5747. status = ERROR_CLUSTER_NODE_NOT_FOUND;
  5748. ClRtlLogPrint(LOG_CRITICAL,
  5749. "[NM] Node %1!ws! does not exist. Cannot create interface %2!ws!\n",
  5750. InterfaceInfo->NodeId,
  5751. InterfaceInfo->Id
  5752. );
  5753. goto error_exit;
  5754. }
  5755. //
  5756. // Verify that the interface doesn't already exist.
  5757. //
  5758. NmpAcquireLock();
  5759. for ( entry = node->InterfaceList.Flink;
  5760. entry != &(node->InterfaceList);
  5761. entry = entry->Flink
  5762. )
  5763. {
  5764. netInterface = CONTAINING_RECORD(entry, NM_INTERFACE, NodeLinkage);
  5765. if (netInterface->Network == network) {
  5766. status = ERROR_CLUSTER_NETINTERFACE_EXISTS;
  5767. ClRtlLogPrint(LOG_CRITICAL,
  5768. "[NM] An interface already exists for node %1!ws! on network %2!ws!\n",
  5769. InterfaceInfo->NodeId,
  5770. InterfaceInfo->NetworkId
  5771. );
  5772. NmpReleaseLock();
  5773. goto error_exit;
  5774. }
  5775. }
  5776. NmpReleaseLock();
  5777. //
  5778. // Verify that the specified interface ID is unique.
  5779. //
  5780. netInterface = OmReferenceObjectById(
  5781. ObjectTypeNetInterface,
  5782. InterfaceInfo->Id
  5783. );
  5784. if (netInterface != NULL) {
  5785. OmDereferenceObject(netInterface);
  5786. status = ERROR_CLUSTER_NETINTERFACE_EXISTS;
  5787. ClRtlLogPrint(LOG_CRITICAL,
  5788. "[NM] An interface with ID %1!ws! already exists\n",
  5789. InterfaceInfo->Id
  5790. );
  5791. goto error_exit;
  5792. }
  5793. *Node = node;
  5794. *Network = network;
  5795. return(ERROR_SUCCESS);
  5796. error_exit:
  5797. if (network != NULL) {
  5798. OmDereferenceObject(network);
  5799. }
  5800. if (node != NULL) {
  5801. OmDereferenceObject(node);
  5802. }
  5803. return(status);
  5804. } // NmpPrepareToCreateInterface
  5805. PNM_INTERFACE
  5806. NmpGetInterfaceForNodeAndNetworkById(
  5807. IN CL_NODE_ID NodeId,
  5808. IN CL_NETWORK_ID NetworkId
  5809. )
  5810. /*++
  5811. Routine Description:
  5812. Give the node Id and network short Id, return a pointer to
  5813. the intersecting interface object
  5814. Arguments:
  5815. NodeId - The ID of the node associated with this interface
  5816. NetworkId - The short Id of the network associated with this interface
  5817. Return Value:
  5818. A pointer to the interface object if successful.
  5819. NULL if unsuccessful. Extended error information is available from
  5820. GetLastError().
  5821. Notes:
  5822. Called with the NmpLock held.
  5823. --*/
  5824. {
  5825. DWORD status;
  5826. PNM_NODE node = NmpIdArray[NodeId];
  5827. if (node != NULL) {
  5828. PLIST_ENTRY entry;
  5829. PNM_INTERFACE netInterface;
  5830. //
  5831. // run down the list of interfaces associated with this node,
  5832. // looking for one whose network matches the specified short ID
  5833. //
  5834. for (entry = node->InterfaceList.Flink;
  5835. entry != &(node->InterfaceList);
  5836. entry = entry->Flink
  5837. )
  5838. {
  5839. netInterface = CONTAINING_RECORD(
  5840. entry,
  5841. NM_INTERFACE,
  5842. NodeLinkage
  5843. );
  5844. if (netInterface->Network->ShortId == NetworkId) {
  5845. return(netInterface);
  5846. }
  5847. }
  5848. status = ERROR_CLUSTER_NETINTERFACE_NOT_FOUND;
  5849. }
  5850. else {
  5851. status = ERROR_CLUSTER_NODE_NOT_FOUND;
  5852. }
  5853. SetLastError(status);
  5854. return(NULL);
  5855. } // NmpGetInterfaceForNodeAndNetworkById
  5856. DWORD
  5857. NmpConvertPropertyListToInterfaceInfo(
  5858. IN PVOID InterfacePropertyList,
  5859. IN DWORD InterfacePropertyListSize,
  5860. PNM_INTERFACE_INFO2 InterfaceInfo
  5861. )
  5862. {
  5863. DWORD status;
  5864. //
  5865. // Unmarshall the property list.
  5866. //
  5867. ZeroMemory(InterfaceInfo, sizeof(NM_INTERFACE_INFO2));
  5868. status = ClRtlVerifyPropertyTable(
  5869. NmpInterfaceProperties,
  5870. NULL, // Reserved
  5871. FALSE, // Don't allow unknowns
  5872. InterfacePropertyList,
  5873. InterfacePropertyListSize,
  5874. (LPBYTE) InterfaceInfo
  5875. );
  5876. if (status == ERROR_SUCCESS) {
  5877. InterfaceInfo->NetIndex = NmInvalidInterfaceNetIndex;
  5878. }
  5879. return(status);
  5880. } // NmpConvertPropertyListToInterfaceInfo
  5881. BOOLEAN
  5882. NmpVerifyLocalInterfaceConnected(
  5883. IN PNM_INTERFACE Interface
  5884. )
  5885. /*++
  5886. Routine Description:
  5887. Queries local interface adapter for current media
  5888. status using an NDIS ioctl.
  5889. Arguments:
  5890. Interface - interface object for local adapter to query
  5891. Return value:
  5892. TRUE if media status is connected or cannot be determined
  5893. FALSE if media status is disconnected
  5894. Notes:
  5895. Called and returns with NM lock acquired.
  5896. --*/
  5897. {
  5898. PWCHAR adapterDevNameBuffer = NULL;
  5899. PWCHAR adapterDevNamep, prefix, brace;
  5900. DWORD prefixSize, allocSize, adapterIdSize;
  5901. DWORD status = ERROR_SUCCESS;
  5902. UNICODE_STRING adapterDevName;
  5903. NIC_STATISTICS ndisStats;
  5904. BOOLEAN mediaConnected = TRUE;
  5905. // verify parameters
  5906. if (Interface == NULL || Interface->AdapterId == NULL) {
  5907. return TRUE;
  5908. }
  5909. // the adapter device name is of the form
  5910. //
  5911. // \Device\{AdapterIdGUID}
  5912. //
  5913. // the AdapterId field in the NM_INTERFACE structure is
  5914. // currently not enclosed in braces, but we handle the
  5915. // case where it is.
  5916. // set up the adapter device name prefix
  5917. prefix = L"\\Device\\";
  5918. prefixSize = wcslen(prefix) * sizeof(WCHAR);
  5919. // allocate a buffer for the adapter device name.
  5920. adapterIdSize = wcslen(Interface->AdapterId) * sizeof(WCHAR);
  5921. allocSize = prefixSize + adapterIdSize + sizeof(UNICODE_NULL);
  5922. brace = L"{";
  5923. if (*((PWCHAR)Interface->AdapterId) != *brace) {
  5924. allocSize += 2 * sizeof(WCHAR);
  5925. }
  5926. adapterDevNameBuffer = LocalAlloc(LMEM_FIXED, allocSize);
  5927. if (adapterDevNameBuffer == NULL) {
  5928. ClRtlLogPrint(
  5929. LOG_UNUSUAL,
  5930. "[NM] Failed to allocate device name buffer for "
  5931. "adapter %1!ws!. Assuming adapter is connected.\n",
  5932. Interface->AdapterId
  5933. );
  5934. return(TRUE);
  5935. }
  5936. // build the adapter device name from the adapter ID
  5937. ZeroMemory(adapterDevNameBuffer, allocSize);
  5938. adapterDevNamep = adapterDevNameBuffer;
  5939. CopyMemory(adapterDevNamep, prefix, prefixSize);
  5940. adapterDevNamep += prefixSize / sizeof(WCHAR);
  5941. if (*((PWCHAR)Interface->AdapterId) != *brace) {
  5942. *adapterDevNamep = *brace;
  5943. adapterDevNamep++;
  5944. }
  5945. CopyMemory(adapterDevNamep, Interface->AdapterId, adapterIdSize);
  5946. if (*((PWCHAR)Interface->AdapterId) != *brace) {
  5947. brace = L"}";
  5948. adapterDevNamep += adapterIdSize / sizeof(WCHAR);
  5949. *adapterDevNamep = *brace;
  5950. }
  5951. RtlInitUnicodeString(&adapterDevName, (LPWSTR)adapterDevNameBuffer);
  5952. // query the adapter for NDIS statistics
  5953. ZeroMemory(&ndisStats, sizeof(ndisStats));
  5954. ndisStats.Size = sizeof(ndisStats);
  5955. if (!NdisQueryStatistics(&adapterDevName, &ndisStats)) {
  5956. status = GetLastError();
  5957. ClRtlLogPrint(
  5958. LOG_UNUSUAL,
  5959. "[NM] NDIS statistics query to adapter %1!ws! failed, "
  5960. "error %2!u!. Assuming adapter is connected.\n",
  5961. Interface->AdapterId, status
  5962. );
  5963. } else {
  5964. if (ndisStats.MediaState == MEDIA_STATE_DISCONNECTED) {
  5965. mediaConnected = FALSE;
  5966. }
  5967. }
  5968. LocalFree(adapterDevNameBuffer);
  5969. return(mediaConnected);
  5970. } // NmpVerifyLocalInterfaceConnected