Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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