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.

4895 lines
124 KiB

  1. /*++
  2. Copyright (c) 1992-1999 Microsoft Corporation
  3. Module Name:
  4. ipaddr.c
  5. Abstract:
  6. Resource DLL for an IP address.
  7. Author:
  8. Mike Massa (mikemas) 29-Dec-1995
  9. Revision History:
  10. --*/
  11. #define UNICODE 1
  12. #include "clusres.h"
  13. #include "clusrtl.h"
  14. #include <winsock.h>
  15. #include <ipexport.h>
  16. #include <icmpapi.h>
  17. #include "util.h"
  18. #include "nteapi.h"
  19. #include <dnsapi.h>
  20. //
  21. // Private Constants
  22. //
  23. #define LOG_CURRENT_MODULE LOG_MODULE_IPADDR
  24. #define INVALID_NTE_CONTEXT 0xFFFFFFFF
  25. #define MAX_NODE_ID_LENGTH 5
  26. #define NETINTERFACE_ID_LENGTH 36 // size of a guid
  27. #define NETWORK_ID_LENGTH 36
  28. #define PROP_NAME__NETWORK CLUSREG_NAME_IPADDR_NETWORK
  29. #define PROP_NAME__ADDRESS CLUSREG_NAME_IPADDR_ADDRESS
  30. #define PROP_NAME__SUBNETMASK CLUSREG_NAME_IPADDR_SUBNET_MASK
  31. #define PROP_NAME__ENABLENETBIOS CLUSREG_NAME_IPADDR_ENABLE_NETBIOS
  32. //
  33. // Private Macros
  34. //
  35. #define IpaLogEvent ClusResLogEvent
  36. #define IpaSetResourceStatus ClusResSetResourceStatus
  37. #define ARGUMENT_PRESENT( ArgumentPointer ) (\
  38. (CHAR *)(ArgumentPointer) != (CHAR *)(NULL) )
  39. #define IpaAcquireGlobalLock() \
  40. { \
  41. DWORD status; \
  42. status = WaitForSingleObject(IpaGlobalMutex, INFINITE); \
  43. }
  44. #define IpaReleaseGlobalLock() \
  45. { \
  46. BOOL released; \
  47. released = ReleaseMutex(IpaGlobalMutex); \
  48. }
  49. #define IpaAcquireResourceLock(_res) EnterCriticalSection(&((_res)->Lock))
  50. #define IpaReleaseResourceLock(_res) LeaveCriticalSection(&((_res)->Lock))
  51. #define DBG_PRINT printf
  52. //
  53. // Private Types.
  54. //
  55. typedef struct _IPA_PRIVATE_PROPS {
  56. PWSTR NetworkString;
  57. PWSTR AddressString;
  58. PWSTR SubnetMaskString;
  59. DWORD EnableNetbios;
  60. } IPA_PRIVATE_PROPS, *PIPA_PRIVATE_PROPS;
  61. typedef struct _IPA_LOCAL_PARAMS {
  62. LPWSTR InterfaceId;
  63. LPWSTR InterfaceName;
  64. LPWSTR AdapterName;
  65. LPWSTR AdapterId;
  66. IPAddr NbtPrimaryWinsAddress;
  67. IPAddr NbtSecondaryWinsAddress;
  68. } IPA_LOCAL_PARAMS, *PIPA_LOCAL_PARAMS;
  69. typedef struct {
  70. LIST_ENTRY Linkage;
  71. CLUSTER_RESOURCE_STATE State;
  72. DWORD FailureStatus;
  73. RESOURCE_HANDLE ResourceHandle;
  74. BOOLEAN InternalParametersInitialized;
  75. IPAddr Address;
  76. IPMask SubnetMask;
  77. DWORD EnableNetbios;
  78. IPA_PRIVATE_PROPS InternalPrivateProps;
  79. IPA_LOCAL_PARAMS LocalParams;
  80. HNETINTERFACE InterfaceHandle;
  81. DWORD NteContext;
  82. DWORD NteInstance;
  83. LPWSTR NbtDeviceName;
  84. DWORD NbtDeviceInstance;
  85. CLUS_WORKER OnlineThread;
  86. HKEY ResourceKey;
  87. HKEY ParametersKey;
  88. HKEY NodeParametersKey;
  89. HKEY NetworksKey;
  90. HKEY InterfacesKey;
  91. WCHAR NodeId[MAX_NODE_ID_LENGTH + 1];
  92. CRITICAL_SECTION Lock;
  93. } IPA_RESOURCE, *PIPA_RESOURCE;
  94. //
  95. // Private Data
  96. //
  97. HANDLE IpaGlobalMutex = NULL;
  98. USHORT IpaResourceInstance = 0;
  99. HCLUSTER IpaClusterHandle = NULL;
  100. HCHANGE IpaClusterNotifyHandle = NULL;
  101. HANDLE IpaWorkerThreadHandle = NULL;
  102. DWORD IpaOpenResourceCount = 0;
  103. DWORD IpaOnlineResourceCount = 0;
  104. LIST_ENTRY IpaResourceList = {NULL, NULL};
  105. WCHAR NbtDevicePrefix[] = L"\\Device\\NetBT_Tcpip_{";
  106. WCHAR NbtDeviceSuffix[] = L"}";
  107. DWORD IpaMaxIpAddressStringLength = 0;
  108. RESUTIL_PROPERTY_ITEM
  109. IpaResourcePrivateProperties[] = {
  110. { PROP_NAME__NETWORK,
  111. NULL,
  112. CLUSPROP_FORMAT_SZ,
  113. 0, 0, 0, RESUTIL_PROPITEM_REQUIRED,
  114. FIELD_OFFSET(IPA_PRIVATE_PROPS,NetworkString)
  115. },
  116. { PROP_NAME__ADDRESS,
  117. NULL,
  118. CLUSPROP_FORMAT_SZ,
  119. 0, 0, 0, RESUTIL_PROPITEM_REQUIRED,
  120. FIELD_OFFSET(IPA_PRIVATE_PROPS,AddressString)
  121. },
  122. { PROP_NAME__SUBNETMASK,
  123. NULL,
  124. CLUSPROP_FORMAT_SZ,
  125. 0, 0, 0, RESUTIL_PROPITEM_REQUIRED,
  126. FIELD_OFFSET(IPA_PRIVATE_PROPS,SubnetMaskString)
  127. },
  128. { PROP_NAME__ENABLENETBIOS,
  129. NULL,
  130. CLUSPROP_FORMAT_DWORD,
  131. 1, 0, 0xFFFFFFFF, 0,
  132. FIELD_OFFSET(IPA_PRIVATE_PROPS,EnableNetbios)
  133. },
  134. { 0 }
  135. };
  136. //
  137. // External Data
  138. //
  139. extern CLRES_FUNCTION_TABLE IpAddrFunctionTable;
  140. //
  141. // Private Routine Headers
  142. //
  143. DWORD
  144. IpaGetPrivateResProperties(
  145. IN OUT PIPA_RESOURCE ResourceEntry,
  146. OUT PVOID OutBuffer,
  147. IN DWORD OutBufferSize,
  148. OUT LPDWORD BytesReturned
  149. );
  150. DWORD
  151. IpaValidatePrivateResProperties(
  152. IN OUT PIPA_RESOURCE ResourceEntry,
  153. IN PVOID InBuffer,
  154. IN DWORD InBufferSize,
  155. OUT PIPA_PRIVATE_PROPS Props
  156. );
  157. DWORD
  158. IpaSetPrivateResProperties(
  159. IN OUT PIPA_RESOURCE ResourceEntry,
  160. IN PVOID InBuffer,
  161. IN DWORD InBufferSize
  162. );
  163. DWORD
  164. IpaWorkerThread(
  165. LPVOID Context
  166. );
  167. VOID
  168. WINAPI
  169. IpaClose(
  170. IN RESID Resource
  171. );
  172. //
  173. // Utility functions
  174. //
  175. BOOLEAN
  176. IpaInit(
  177. VOID
  178. )
  179. /*++
  180. Routine Description:
  181. Process attach initialization routine.
  182. Arguments:
  183. None.
  184. Return Value:
  185. TRUE if initialization succeeded. FALSE otherwise.
  186. --*/
  187. {
  188. INT err;
  189. WSADATA WsaData;
  190. InitializeListHead(&IpaResourceList);
  191. ClRtlQueryTcpipInformation(&IpaMaxIpAddressStringLength, NULL, NULL);
  192. err = WSAStartup(0x0101, &WsaData);
  193. if (err) {
  194. return(FALSE);
  195. }
  196. IpaGlobalMutex = CreateMutex(NULL, FALSE, NULL);
  197. if (IpaGlobalMutex == NULL) {
  198. WSACleanup();
  199. return(FALSE);
  200. }
  201. return(TRUE);
  202. } // IpaInit
  203. VOID
  204. IpaCleanup(
  205. VOID
  206. )
  207. /*++
  208. Routine Description:
  209. Process detach cleanup routine.
  210. Arguments:
  211. None.
  212. Return Value:
  213. None.
  214. --*/
  215. {
  216. if (IpaGlobalMutex != NULL) {
  217. CloseHandle(IpaGlobalMutex);
  218. IpaGlobalMutex = NULL;
  219. }
  220. WSACleanup();
  221. return;
  222. }
  223. LPWSTR
  224. IpaGetNameOfNetwork(
  225. IN OUT PIPA_RESOURCE ResourceEntry,
  226. IN LPCWSTR NetworkId
  227. )
  228. /*++
  229. Routine Description:
  230. Get the name of a network from its GUID.
  231. Arguments:
  232. ResourceEntry - Supplies the resource entry on which to operate.
  233. NetworkId - Supplies the ID of the network.
  234. Return Value:
  235. String allocated using LocalAlloc() containing the name of the
  236. network.
  237. NULL - An error occurred getting the name of the network. Call
  238. GetLastError() for more details.
  239. --*/
  240. {
  241. DWORD status;
  242. DWORD ival;
  243. DWORD type;
  244. DWORD nameLength;
  245. WCHAR name[256];
  246. LPWSTR networkName = NULL;
  247. HKEY networkKey = NULL;
  248. FILETIME fileTime;
  249. //
  250. // Enumerate the networks, looking for the specified GUID.
  251. //
  252. for ( ival = 0 ; ; ival++ ) {
  253. nameLength = sizeof(name);
  254. status = ClusterRegEnumKey( ResourceEntry->NetworksKey,
  255. ival,
  256. name,
  257. &nameLength,
  258. &fileTime );
  259. if ( status == ERROR_MORE_DATA ) {
  260. continue;
  261. }
  262. if ( status != ERROR_SUCCESS ) {
  263. break;
  264. }
  265. //
  266. // If we found a match, open the key and read the name.
  267. //
  268. if ( lstrcmpiW( name, NetworkId ) == 0 ) {
  269. status = ClusterRegOpenKey( ResourceEntry->NetworksKey,
  270. name,
  271. KEY_READ,
  272. &networkKey );
  273. if ( status != ERROR_SUCCESS ) {
  274. goto error_exit;
  275. }
  276. //
  277. // Get the size of the name value.
  278. //
  279. status = ClusterRegQueryValue( networkKey,
  280. CLUSREG_NAME_NET_NAME,
  281. &type,
  282. NULL,
  283. &nameLength );
  284. if ( status != ERROR_SUCCESS ) {
  285. goto error_exit;
  286. }
  287. //
  288. // Allocate memory for the network name.
  289. //
  290. networkName = LocalAlloc( LMEM_FIXED, nameLength );
  291. if ( networkName == NULL ) {
  292. status = GetLastError();
  293. goto error_exit;
  294. }
  295. //
  296. // Read the name value.
  297. //
  298. status = ClusterRegQueryValue( networkKey,
  299. CLUSREG_NAME_NET_NAME,
  300. &type,
  301. (LPBYTE) networkName,
  302. &nameLength );
  303. if ( status != ERROR_SUCCESS ) {
  304. LocalFree( networkName );
  305. networkName = NULL;
  306. goto error_exit;
  307. }
  308. break;
  309. }
  310. }
  311. error_exit:
  312. if ( networkKey != NULL ) {
  313. ClusterRegCloseKey( networkKey );
  314. }
  315. if ( status != ERROR_SUCCESS ) {
  316. SetLastError( status );
  317. }
  318. return(networkName);
  319. } // IpaGetNameOfNetwork
  320. PWCHAR
  321. WcsDup(
  322. IN PWCHAR str
  323. )
  324. /*++
  325. Routine Description:
  326. Duplicates the string.
  327. It does the same as _wcsdup, except that
  328. it uses LocalAlloc for allocation
  329. Arguments:
  330. str - string to be copied
  331. Return Value:
  332. String allocated using LocalAlloc() containing the copy
  333. of str.
  334. NULL - not enough memory
  335. --*/
  336. {
  337. UINT n = (wcslen(str) + 1) * sizeof(WCHAR);
  338. PWCHAR result = LocalAlloc( LMEM_FIXED , n );
  339. if (result) {
  340. CopyMemory( result, str, n );
  341. }
  342. return result;
  343. }
  344. DWORD
  345. IpaPatchNetworkGuidIfNecessary(
  346. IN OUT PIPA_RESOURCE ResourceEntry,
  347. IN OUT PIPA_PRIVATE_PROPS props
  348. )
  349. /*++
  350. Routine Description:
  351. Check whether network GUID exists in cluster registry
  352. If there is no such network,
  353. it will try to find a compatible network
  354. Arguments:
  355. ResourceEntry - Supplies the resource entry on which to operate.
  356. props - Supplies IP address properties.
  357. Return Value:
  358. String allocated using LocalAlloc() containing the name of the
  359. network.
  360. NULL - An error occurred getting the name of the network. Call
  361. GetLastError() for more details.
  362. --*/
  363. {
  364. DWORD status = ERROR_SUCCESS;
  365. DWORD ival;
  366. DWORD type;
  367. DWORD bufLength;
  368. WCHAR buf[256];
  369. DWORD nameLength;
  370. WCHAR name[256];
  371. PWCHAR match = NULL;
  372. ULONG networkAddr;
  373. ULONG networkMask;
  374. ULONG ipAddr;
  375. ULONG ipAddrMask;
  376. BOOLEAN guidFound = FALSE;
  377. HKEY networkKey = NULL;
  378. FILETIME fileTime;
  379. if (props == NULL) {
  380. return ERROR_SUCCESS;
  381. }
  382. if ( props->NetworkString == NULL ) {
  383. return ERROR_SUCCESS;
  384. }
  385. if ( props->AddressString == NULL
  386. || !UnicodeInetAddr(props->AddressString, &ipAddr) )
  387. {
  388. return ERROR_SUCCESS;
  389. }
  390. if ( props->SubnetMaskString == NULL
  391. || !UnicodeInetAddr(props->SubnetMaskString, &ipAddrMask) )
  392. {
  393. return ERROR_SUCCESS;
  394. }
  395. //
  396. // Enumerate the networks, looking for the specified GUID.
  397. //
  398. for ( ival = 0 ; ; ival++ ) {
  399. nameLength = sizeof(name);
  400. status = ClusterRegEnumKey( ResourceEntry->NetworksKey,
  401. ival,
  402. name,
  403. &nameLength,
  404. &fileTime );
  405. if ( status == ERROR_MORE_DATA ) {
  406. continue;
  407. }
  408. if ( status != ERROR_SUCCESS ) {
  409. break;
  410. }
  411. //
  412. // If we found a match, then we don't have to do anything
  413. //
  414. if ( lstrcmpiW( name, props->NetworkString ) == 0 ) {
  415. guidFound = TRUE;
  416. break;
  417. }
  418. if ( networkKey != NULL ) {
  419. ClusterRegCloseKey( networkKey );
  420. networkKey = NULL;
  421. }
  422. //
  423. // Check whether ip address fit this network
  424. //
  425. status = ClusterRegOpenKey( ResourceEntry->NetworksKey,
  426. name,
  427. KEY_READ,
  428. &networkKey );
  429. if ( status != ERROR_SUCCESS ) {
  430. continue;
  431. }
  432. //
  433. // Get the network address
  434. //
  435. bufLength = sizeof(buf);
  436. status = ClusterRegQueryValue( networkKey,
  437. CLUSREG_NAME_NET_ADDRESS,
  438. &type,
  439. (LPBYTE)buf,
  440. &bufLength );
  441. if ( status != ERROR_SUCCESS
  442. || !UnicodeInetAddr(buf, &networkAddr) )
  443. {
  444. continue;
  445. }
  446. //
  447. // Get subnet mask
  448. //
  449. bufLength = sizeof(buf);
  450. status = ClusterRegQueryValue( networkKey,
  451. CLUSREG_NAME_NET_ADDRESS_MASK,
  452. &type,
  453. (LPBYTE)buf,
  454. &bufLength );
  455. if ( status != ERROR_SUCCESS
  456. || !UnicodeInetAddr(buf, &networkMask) )
  457. {
  458. continue;
  459. }
  460. (IpaLogEvent)(
  461. ResourceEntry->ResourceHandle,
  462. LOG_INFORMATION,
  463. L"Checking if resource is orphaned: network masks %1!08X!=%2!08X! "
  464. L"and addresses %3!08X!^%4!08X!.\n",
  465. ipAddrMask, networkMask,
  466. ipAddr, networkAddr
  467. );
  468. if ( networkMask != ipAddrMask) {
  469. continue;
  470. }
  471. if ( ((ipAddr ^ networkAddr) & networkMask) != 0 ) {
  472. continue;
  473. }
  474. //
  475. // Okay we've found a suitable network
  476. // create a string with its name
  477. //
  478. match = WcsDup( name );
  479. break;
  480. }
  481. if ( !guidFound && match ) {
  482. //
  483. // We need to patch network information
  484. //
  485. LocalFree(props->NetworkString);
  486. props->NetworkString = match;
  487. status = ClusterRegSetValue(
  488. ResourceEntry->ParametersKey,
  489. CLUSREG_NAME_IPADDR_NETWORK,
  490. REG_SZ,
  491. (LPBYTE) match,
  492. (wcslen(match) + 1) * sizeof(WCHAR)
  493. );
  494. (IpaLogEvent)(
  495. ResourceEntry->ResourceHandle,
  496. LOG_WARNING,
  497. L"Patch with network GUID %2!ws!, status %1!u!.\n",
  498. status,
  499. match
  500. );
  501. match = NULL;
  502. }
  503. if ( networkKey != NULL ) {
  504. ClusterRegCloseKey( networkKey );
  505. }
  506. if ( status != ERROR_SUCCESS ) {
  507. SetLastError( status );
  508. }
  509. if (match != NULL) {
  510. LocalFree(match);
  511. }
  512. return(status);
  513. } // IpaPatchNetworkGuidIfNecessary
  514. LPWSTR
  515. IpaGetNameOfNetworkPatchGuidIfNecessary(
  516. IN OUT PIPA_RESOURCE ResourceEntry,
  517. IN OUT PIPA_PRIVATE_PROPS props
  518. )
  519. /*++
  520. Routine Description:
  521. Get the name of a network from its GUID.
  522. If the guid cannot be found, it will try to find
  523. appropriate network using IpaPatchNetworkGuidIfNecessary routine
  524. Arguments:
  525. ResourceEntry - Supplies the resource entry on which to operate.
  526. props - Supplies IP address properties.
  527. Return Value:
  528. String allocated using LocalAlloc() containing the name of the
  529. network.
  530. NULL - An error occurred getting the name of the network. Call
  531. GetLastError() for more details.
  532. --*/
  533. {
  534. DWORD status;
  535. LPWSTR result = IpaGetNameOfNetwork(ResourceEntry, props->NetworkString);
  536. if (result) {
  537. return result;
  538. }
  539. status = IpaPatchNetworkGuidIfNecessary(ResourceEntry, props);
  540. if (status != ERROR_SUCCESS) {
  541. SetLastError( status );
  542. return 0;
  543. }
  544. return IpaGetNameOfNetwork(ResourceEntry, props->NetworkString);
  545. } // IpaGetNameOfNetworkPatchGuidIfNecessary
  546. LPWSTR
  547. IpaGetIdOfNetwork(
  548. IN OUT PIPA_RESOURCE ResourceEntry,
  549. IN LPCWSTR NetworkName
  550. )
  551. /*++
  552. Routine Description:
  553. Get the ID of a network from its name.
  554. Arguments:
  555. ResourceEntry - Supplies the resource entry on which to operate.
  556. NetworkName - Supplies the name of the network.
  557. Return Value:
  558. String allocated using LocalAlloc() containing the name of the
  559. network.
  560. NULL - An error occurred getting the name of the network. Call
  561. GetLastError() for more details.
  562. --*/
  563. {
  564. DWORD status;
  565. DWORD networkIdLength;
  566. LPWSTR networkId = NULL;
  567. HCLUSTER hcluster = NULL;
  568. HNETWORK hnetwork = NULL;
  569. //
  570. // Open the cluster.
  571. //
  572. hcluster = OpenCluster( NULL );
  573. if ( hcluster == NULL ) {
  574. status = GetLastError();
  575. goto error_exit;
  576. }
  577. //
  578. // Open the network.
  579. //
  580. hnetwork = OpenClusterNetwork( hcluster, NetworkName );
  581. if ( hnetwork == NULL ) {
  582. status = GetLastError();
  583. goto error_exit;
  584. }
  585. //
  586. // Get the network ID length.
  587. //
  588. networkIdLength = 0;
  589. status = GetClusterNetworkId( hnetwork,
  590. NULL,
  591. &networkIdLength );
  592. if ( status != ERROR_SUCCESS ) {
  593. goto error_exit;
  594. }
  595. //
  596. // Allocate a string buffer.
  597. //
  598. networkId = LocalAlloc( LMEM_FIXED, (networkIdLength + 1) * sizeof(WCHAR) );
  599. if ( networkId == NULL ) {
  600. status = GetLastError();
  601. goto error_exit;
  602. }
  603. networkIdLength++;
  604. //
  605. // Get the network ID.
  606. //
  607. status = GetClusterNetworkId( hnetwork,
  608. networkId,
  609. &networkIdLength );
  610. if ( status != ERROR_SUCCESS ) {
  611. LocalFree( networkId );
  612. networkId = NULL;
  613. }
  614. error_exit:
  615. if ( hnetwork != NULL ) {
  616. CloseClusterNetwork( hnetwork );
  617. }
  618. if ( hcluster != NULL ) {
  619. CloseCluster( hcluster );
  620. }
  621. return( networkId );
  622. } // IpaGetIdOfNetwork
  623. VOID
  624. IpaDeleteNte(
  625. IN OUT LPDWORD NteContext,
  626. IN HKEY NodeParametersKey,
  627. IN RESOURCE_HANDLE ResourceHandle
  628. )
  629. /*++
  630. Routine Description:
  631. Deletes a previously created NTE.
  632. Arguments:
  633. NteContext - A pointer to a variable containing the context value
  634. identifying the NTE to delete.
  635. NodeParametersKey - An open handle to the resource's node-specific
  636. parameters key.
  637. ResourceHandle - The Resource Monitor handle associated with this resource.
  638. Return Value:
  639. None.
  640. --*/
  641. {
  642. DWORD status;
  643. ASSERT(*NteContext != INVALID_NTE_CONTEXT);
  644. ASSERT(ResourceHandle != NULL);
  645. (IpaLogEvent)(
  646. ResourceHandle,
  647. LOG_INFORMATION,
  648. L"Deleting IP interface %1!u!.\n",
  649. *NteContext
  650. );
  651. status = TcpipDeleteNTE(*NteContext);
  652. if (status != ERROR_SUCCESS) {
  653. (IpaLogEvent)(
  654. ResourceHandle,
  655. LOG_WARNING,
  656. L"Failed to delete IP interface %1!u!, status %2!u!.\n",
  657. *NteContext,
  658. status
  659. );
  660. }
  661. *NteContext = INVALID_NTE_CONTEXT;
  662. //
  663. // Clear the NTE information from the registry
  664. //
  665. if (NodeParametersKey != NULL) {
  666. status = ClusterRegDeleteValue(
  667. NodeParametersKey,
  668. L"InterfaceContext"
  669. );
  670. if (status != ERROR_SUCCESS) {
  671. (IpaLogEvent)(
  672. ResourceHandle,
  673. LOG_WARNING,
  674. L"Failed to delete IP interface information from database, status %1!u!.\n",
  675. status
  676. );
  677. }
  678. }
  679. return;
  680. } // IpaDeleteNte
  681. DWORD
  682. IpaCreateNte(
  683. IN LPWSTR AdapterId,
  684. IN HKEY NodeParametersKey,
  685. IN RESOURCE_HANDLE ResourceHandle,
  686. OUT LPDWORD NteContext,
  687. OUT LPDWORD NteInstance
  688. )
  689. /*++
  690. Routine Description:
  691. Creates a new NTE to hold an IP address.
  692. Arguments:
  693. AdapterId - A pointer to a buffer containing the unicode name
  694. of the adapter on which the NTE is to be created.
  695. NodeParametersKey - An open handle to the resource's node-specific
  696. parameters key.
  697. ResourceHandle - The Resource Monitor handle associated with this resource.
  698. NteContext - A pointer to a variable into which to place the context value
  699. which identifies the new NTE.
  700. NteInstance - A pointer to a variable into which to place the instance value
  701. which identifies the new NTE.
  702. Return Value:
  703. ERROR_SUCCESS if the routine is successful.
  704. A Win32 error code otherwise.
  705. --*/
  706. {
  707. DWORD status;
  708. *NteContext = INVALID_NTE_CONTEXT;
  709. status = TcpipAddNTE(
  710. AdapterId,
  711. 0,
  712. 0,
  713. NteContext,
  714. NteInstance
  715. );
  716. if (status != ERROR_SUCCESS) {
  717. (IpaLogEvent)(
  718. ResourceHandle,
  719. LOG_ERROR,
  720. L"Unable to create new IP interface, status %1!u!\n",
  721. status);
  722. return(status);
  723. }
  724. //
  725. // Write the NTE information to the registry
  726. //
  727. status = ClusterRegSetValue(
  728. NodeParametersKey,
  729. L"InterfaceContext",
  730. REG_DWORD,
  731. (LPBYTE) NteContext,
  732. sizeof(DWORD)
  733. );
  734. if (status != ERROR_SUCCESS) {
  735. (IpaLogEvent)(
  736. ResourceHandle,
  737. LOG_ERROR,
  738. L"Unable to write IP interface information to database, status %1!u!.\n",
  739. status
  740. );
  741. goto error_exit;
  742. }
  743. status = ClusterRegSetValue(
  744. NodeParametersKey,
  745. L"InterfaceInstance",
  746. REG_DWORD,
  747. (LPBYTE) NteInstance,
  748. sizeof(DWORD)
  749. );
  750. if (status != ERROR_SUCCESS) {
  751. (IpaLogEvent)(
  752. ResourceHandle,
  753. LOG_ERROR,
  754. L"Unable to write IP interface information to database, status %1!u!.\n",
  755. status
  756. );
  757. goto error_exit;
  758. }
  759. (IpaLogEvent)(
  760. ResourceHandle,
  761. LOG_INFORMATION,
  762. L"Created IP interface %1!u! (instance 0x%2!08X!).\n",
  763. *NteContext,
  764. *NteInstance
  765. );
  766. return(ERROR_SUCCESS);
  767. error_exit:
  768. if (*NteContext != INVALID_NTE_CONTEXT) {
  769. IpaDeleteNte(
  770. NteContext,
  771. NodeParametersKey,
  772. ResourceHandle
  773. );
  774. }
  775. return(status);
  776. }
  777. VOID
  778. IpaDeleteNbtInterface(
  779. IN OUT LPWSTR * NbtDeviceName,
  780. IN HKEY NodeParametersKey,
  781. IN RESOURCE_HANDLE ResourceHandle
  782. )
  783. /*++
  784. Routine Description:
  785. Deletes an NBT device (interface).
  786. Arguments:
  787. NbtDeviceName - A pointer to a buffer containing the unicode name
  788. of the NBT device to delete.
  789. NodeParametersKey - An open handle to the resource's node-specific
  790. parameters key.
  791. ResourceHandle - The Resource Monitor handle associated with this resource.
  792. Return Value:
  793. None.
  794. --*/
  795. {
  796. DWORD status;
  797. ASSERT(*NbtDeviceName != NULL);
  798. ASSERT(ResourceHandle != NULL);
  799. (IpaLogEvent)(
  800. ResourceHandle,
  801. LOG_INFORMATION,
  802. L"Deleting NBT interface %1!ws!.\n",
  803. *NbtDeviceName
  804. );
  805. status = NbtDeleteInterface(*NbtDeviceName);
  806. if (status != ERROR_SUCCESS) {
  807. (IpaLogEvent)(
  808. ResourceHandle,
  809. LOG_WARNING,
  810. L"Failed to delete NBT interface %1!ws!, status %2!u!.\n",
  811. *NbtDeviceName,
  812. status
  813. );
  814. }
  815. LocalFree(*NbtDeviceName);
  816. *NbtDeviceName = NULL;
  817. //
  818. // Clear the interface information from the registry
  819. //
  820. if (NodeParametersKey != NULL) {
  821. status = ClusterRegDeleteValue(
  822. NodeParametersKey,
  823. L"NbtDeviceName"
  824. );
  825. if (status != ERROR_SUCCESS) {
  826. (IpaLogEvent)(
  827. ResourceHandle,
  828. LOG_WARNING,
  829. L"Failed to delete NBT interface information from database, status %1!u!.\n",
  830. status
  831. );
  832. }
  833. }
  834. return;
  835. } // IpaDeleteNbtInterface
  836. DWORD
  837. IpaCreateNbtInterface(
  838. IN HKEY NodeParametersKey,
  839. IN RESOURCE_HANDLE ResourceHandle,
  840. OUT LPWSTR * NbtDeviceName,
  841. OUT LPDWORD NbtDeviceInstance
  842. )
  843. /*++
  844. Routine Description:
  845. Creates a new NBT device (interface) to be bound to an IP address.
  846. Arguments:
  847. NodeParametersKey - An open handle to the resource's node-specific
  848. parameters key.
  849. ResourceHandle - The Resource Monitor handle associated with this resource.
  850. NbtDeviceName - A pointer to a buffer into which to place the unicode name
  851. of the new NBT device.
  852. NbtDeviceInstance - A pointer to a variable into which to place the instance
  853. value which identifies the new NBT device.
  854. Return Value:
  855. ERROR_SUCCESS if the routine is successful.
  856. A Win32 error code otherwise.
  857. --*/
  858. {
  859. DWORD status;
  860. DWORD deviceNameSize = 38; // size of L"\\Device\\NetBt_Ifxx\0"
  861. *NbtDeviceName = NULL;
  862. do {
  863. if (*NbtDeviceName != NULL) {
  864. LocalFree(*NbtDeviceName);
  865. *NbtDeviceName = NULL;
  866. }
  867. *NbtDeviceName = LocalAlloc(LMEM_FIXED, deviceNameSize);
  868. if (*NbtDeviceName == NULL) {
  869. (IpaLogEvent)(
  870. ResourceHandle,
  871. LOG_ERROR,
  872. L"Unable to allocate memory.\n");
  873. return(ERROR_NOT_ENOUGH_MEMORY);
  874. }
  875. status = NbtAddInterface(
  876. *NbtDeviceName,
  877. &deviceNameSize,
  878. NbtDeviceInstance
  879. );
  880. } while (status == STATUS_BUFFER_TOO_SMALL);
  881. if (status != ERROR_SUCCESS) {
  882. (IpaLogEvent)(
  883. ResourceHandle,
  884. LOG_ERROR,
  885. L"Unable to create new NBT interface, status %1!u!\n",
  886. status
  887. );
  888. if (*NbtDeviceName != NULL) {
  889. LocalFree(*NbtDeviceName);
  890. *NbtDeviceName = NULL;
  891. }
  892. return(status);
  893. }
  894. status = ClusterRegSetValue(
  895. NodeParametersKey,
  896. L"NbtDeviceName",
  897. REG_SZ,
  898. (LPBYTE) *NbtDeviceName,
  899. (lstrlenW(*NbtDeviceName) + 1) * sizeof(WCHAR)
  900. );
  901. if (status != ERROR_SUCCESS) {
  902. (IpaLogEvent)(
  903. ResourceHandle,
  904. LOG_ERROR,
  905. L"Unable to write NBT interface information to database, status %1!u!.\n",
  906. status
  907. );
  908. goto error_exit;
  909. }
  910. status = ClusterRegSetValue(
  911. NodeParametersKey,
  912. L"NbtDeviceInstance",
  913. REG_DWORD,
  914. (LPBYTE) NbtDeviceInstance,
  915. sizeof(DWORD)
  916. );
  917. if (status != ERROR_SUCCESS) {
  918. (IpaLogEvent)(
  919. ResourceHandle,
  920. LOG_ERROR,
  921. L"Unable to write NBT interface information to database, status %1!u!.\n",
  922. status
  923. );
  924. goto error_exit;
  925. }
  926. (IpaLogEvent)(
  927. ResourceHandle,
  928. LOG_INFORMATION,
  929. L"Created NBT interface %1!ws! (instance 0x%2!08X!).\n",
  930. *NbtDeviceName,
  931. *NbtDeviceInstance
  932. );
  933. return(ERROR_SUCCESS);
  934. error_exit:
  935. if (*NbtDeviceName != NULL) {
  936. IpaDeleteNbtInterface(
  937. NbtDeviceName,
  938. NodeParametersKey,
  939. ResourceHandle
  940. );
  941. }
  942. return(status);
  943. }
  944. VOID
  945. IpaLastOfflineCleanup(
  946. VOID
  947. )
  948. /*++
  949. Notes:
  950. Called with IpaGlobalLock held.
  951. Returns with IpaGlobalLock released.
  952. --*/
  953. {
  954. HCHANGE notifyHandle = IpaClusterNotifyHandle;
  955. HANDLE workerThreadHandle = IpaWorkerThreadHandle;
  956. if (!IsListEmpty(&IpaResourceList)) {
  957. PIPA_RESOURCE resource;
  958. resource = CONTAINING_RECORD(
  959. IpaResourceList.Flink,
  960. IPA_RESOURCE,
  961. Linkage
  962. );
  963. (IpaLogEvent)(
  964. resource->ResourceHandle,
  965. LOG_INFORMATION,
  966. L"All resources offline - cleaning up\n"
  967. );
  968. }
  969. IpaClusterNotifyHandle = NULL;
  970. IpaWorkerThreadHandle = NULL;
  971. IpaReleaseGlobalLock();
  972. if (notifyHandle != NULL) {
  973. CloseClusterNotifyPort(notifyHandle);
  974. }
  975. if (workerThreadHandle != NULL) {
  976. WaitForSingleObject(workerThreadHandle, INFINITE);
  977. CloseHandle(workerThreadHandle);
  978. }
  979. return;
  980. } // IpaLastOfflineCleanup
  981. DWORD
  982. IpaFirstOnlineInit(
  983. IN RESOURCE_HANDLE ResourceHandle
  984. )
  985. /*++
  986. Notes:
  987. Called with IpaGlobalLock held.
  988. Returns with IpaGlobalLock released.
  989. --*/
  990. {
  991. DWORD status = ERROR_SUCCESS;
  992. DWORD threadId;
  993. IpaClusterNotifyHandle = CreateClusterNotifyPort(
  994. INVALID_HANDLE_VALUE,
  995. IpaClusterHandle,
  996. CLUSTER_CHANGE_HANDLE_CLOSE,
  997. 0
  998. );
  999. if (IpaClusterNotifyHandle == NULL) {
  1000. status = GetLastError();
  1001. (IpaLogEvent)(
  1002. ResourceHandle,
  1003. LOG_ERROR,
  1004. L"Unable to create cluster notify port, status %1!u!.\n",
  1005. status
  1006. );
  1007. goto error_exit;
  1008. }
  1009. else {
  1010. (IpaLogEvent)(
  1011. ResourceHandle,
  1012. LOG_INFORMATION,
  1013. L"Created cluster notify port.\n"
  1014. );
  1015. }
  1016. IpaWorkerThreadHandle = CreateThread(
  1017. NULL,
  1018. 0,
  1019. IpaWorkerThread,
  1020. NULL,
  1021. 0,
  1022. &threadId
  1023. );
  1024. if (IpaWorkerThreadHandle == NULL) {
  1025. status = GetLastError();
  1026. (IpaLogEvent)(
  1027. ResourceHandle,
  1028. LOG_ERROR,
  1029. L"Unable to create worker thread, status %1!u!.\n",
  1030. status
  1031. );
  1032. goto error_exit;
  1033. }
  1034. else {
  1035. (IpaLogEvent)(
  1036. ResourceHandle,
  1037. LOG_INFORMATION,
  1038. L"Created worker thread.\n"
  1039. );
  1040. }
  1041. IpaReleaseGlobalLock();
  1042. return(ERROR_SUCCESS);
  1043. error_exit:
  1044. IpaLastOfflineCleanup();
  1045. //
  1046. // The lock was released.
  1047. //
  1048. return(status);
  1049. } // IpaFirstOnlineInit
  1050. PIPA_RESOURCE
  1051. IpaFindResourceInList(
  1052. PVOID Key
  1053. )
  1054. {
  1055. PIPA_RESOURCE resource;
  1056. PLIST_ENTRY entry;
  1057. for ( entry = IpaResourceList.Flink;
  1058. entry != &IpaResourceList;
  1059. entry = entry->Flink
  1060. )
  1061. {
  1062. resource = CONTAINING_RECORD(
  1063. entry,
  1064. IPA_RESOURCE,
  1065. Linkage
  1066. );
  1067. if (resource == Key) {
  1068. return(resource);
  1069. }
  1070. }
  1071. return(NULL);
  1072. } // IpaFindResourceInList
  1073. VOID
  1074. IpaValidateAndOfflineInterfaces(
  1075. IN PIPA_RESOURCE Resource
  1076. )
  1077. {
  1078. DWORD status;
  1079. //
  1080. // Take care of NBT first.
  1081. //
  1082. if (Resource->NbtDeviceName != NULL) {
  1083. DWORD instance;
  1084. IPAddr boundAddress;
  1085. //
  1086. // Make sure that this is still our interface.
  1087. //
  1088. status = NbtGetInterfaceInfo(
  1089. Resource->NbtDeviceName,
  1090. &boundAddress,
  1091. &instance
  1092. );
  1093. if ( (status == ERROR_SUCCESS) &&
  1094. (Resource->NbtDeviceInstance == instance)
  1095. )
  1096. {
  1097. //
  1098. // Clear the WINS addresses
  1099. //
  1100. status = NbtSetWinsAddrInterface(Resource->NbtDeviceName, 0, 0);
  1101. if (status != NO_ERROR) {
  1102. (IpaLogEvent)(
  1103. Resource->ResourceHandle,
  1104. LOG_WARNING,
  1105. L"Failed to clear WINS addresses for NBT device %1!ws!, status %2!u!.\n",
  1106. Resource->NbtDeviceName,
  1107. status
  1108. );
  1109. }
  1110. //
  1111. // Unbind the interface from IP if necessary
  1112. //
  1113. if (boundAddress != 0) {
  1114. status = NbtBindInterface(Resource->NbtDeviceName, 0, 0);
  1115. if (status != ERROR_SUCCESS) {
  1116. //
  1117. // Delete the interface, since it is misbehaving.
  1118. //
  1119. (IpaLogEvent)(
  1120. Resource->ResourceHandle,
  1121. LOG_WARNING,
  1122. L"Failed to unbind NBT device %1!ws!, status %2!u!.\n",
  1123. Resource->NbtDeviceName,
  1124. status
  1125. );
  1126. IpaDeleteNbtInterface(
  1127. &(Resource->NbtDeviceName),
  1128. Resource->NodeParametersKey,
  1129. Resource->ResourceHandle
  1130. );
  1131. }
  1132. }
  1133. }
  1134. else {
  1135. //
  1136. // Querying the NBT interface failed. See if we can determine
  1137. // why.
  1138. //
  1139. if (status == ERROR_WORKING_SET_QUOTA
  1140. || status == ERROR_NO_SYSTEM_RESOURCES) {
  1141. //
  1142. // The NBT ioctl probably failed due to low resources.
  1143. // Leave record of the NBT interface in our database. We
  1144. // will clean it up next time we try to bring this resource
  1145. // on-line or (via clusnet) when the cluster service shuts
  1146. // down.
  1147. //
  1148. (IpaLogEvent)(
  1149. Resource->ResourceHandle,
  1150. LOG_INFORMATION,
  1151. L"NBT interface %1!ws! (instance 0x%2!08X!) could not be queried, status %3!u!.\n",
  1152. Resource->NbtDeviceName,
  1153. Resource->NbtDeviceInstance,
  1154. status
  1155. );
  1156. }
  1157. else {
  1158. //
  1159. // The interface is no longer valid or it isn't ours.
  1160. // Forget about it.
  1161. //
  1162. (IpaLogEvent)(
  1163. Resource->ResourceHandle,
  1164. LOG_INFORMATION,
  1165. L"NBT interface %1!ws! (instance 0x%2!08X!) is no longer valid, status %3!u!.\n",
  1166. Resource->NbtDeviceName,
  1167. Resource->NbtDeviceInstance,
  1168. status
  1169. );
  1170. LocalFree(Resource->NbtDeviceName);
  1171. Resource->NbtDeviceName = NULL;
  1172. if (Resource->NodeParametersKey != NULL) {
  1173. status = ClusterRegDeleteValue(
  1174. Resource->NodeParametersKey,
  1175. L"NbtDeviceName"
  1176. );
  1177. if (status != ERROR_SUCCESS) {
  1178. (IpaLogEvent)(
  1179. Resource->ResourceHandle,
  1180. LOG_WARNING,
  1181. L"Failed to delete NBT interface information from database, status %1!u!.\n",
  1182. status
  1183. );
  1184. }
  1185. }
  1186. }
  1187. }
  1188. }
  1189. //
  1190. // Now take care of IP
  1191. //
  1192. if (Resource->NteContext != INVALID_NTE_CONTEXT) {
  1193. TCPIP_NTE_INFO nteInfo;
  1194. //
  1195. // Make sure that this is still our interface.
  1196. //
  1197. status = TcpipGetNTEInfo(
  1198. Resource->NteContext,
  1199. &nteInfo
  1200. );
  1201. if ( (status == ERROR_SUCCESS) &&
  1202. (nteInfo.Instance == Resource->NteInstance)
  1203. )
  1204. {
  1205. //
  1206. // In Windows 2000, TCP/IP ignores requests to set the address
  1207. // of an NTE if the underlying interface is disconnected.
  1208. // This can result in the same IP address being brought online
  1209. // on two different nodes. In order to workaround this bug
  1210. // in TCP/IP, we now delete the NTE during offline processing
  1211. // instead of reusing it.
  1212. //
  1213. // Note that IpaDeleteNte() invalidates the value
  1214. // of Resource->NteContext.
  1215. //
  1216. IpaDeleteNte(
  1217. &(Resource->NteContext),
  1218. Resource->NodeParametersKey,
  1219. Resource->ResourceHandle
  1220. );
  1221. #if 0
  1222. //
  1223. // If the NTE is still online, take care of that.
  1224. //
  1225. if (nteInfo.Address != 0) {
  1226. status = TcpipSetNTEAddress(Resource->NteContext, 0, 0);
  1227. if (status != ERROR_SUCCESS) {
  1228. //
  1229. // Delete the interface, since it is misbehaving.
  1230. //
  1231. (IpaLogEvent)(
  1232. Resource->ResourceHandle,
  1233. LOG_WARNING,
  1234. L"Failed to clear address for IP Interface %1!u!, status %2!u!.\n",
  1235. Resource->NteContext,
  1236. status
  1237. );
  1238. IpaDeleteNte(
  1239. &(Resource->NteContext),
  1240. Resource->NodeParametersKey,
  1241. Resource->ResourceHandle
  1242. );
  1243. }
  1244. }
  1245. #endif
  1246. }
  1247. else {
  1248. //
  1249. // The NTE is no longer valid or isn't ours. Forget about it.
  1250. //
  1251. (IpaLogEvent)(
  1252. Resource->ResourceHandle,
  1253. LOG_INFORMATION,
  1254. L"IP interface %1!u! (instance 0x%2!08X!) is no longer valid.\n",
  1255. Resource->NteContext,
  1256. Resource->NteInstance
  1257. );
  1258. Resource->NteContext = INVALID_NTE_CONTEXT;
  1259. if (Resource->NodeParametersKey != NULL) {
  1260. status = ClusterRegDeleteValue(
  1261. Resource->NodeParametersKey,
  1262. L"InterfaceContext"
  1263. );
  1264. if (status != ERROR_SUCCESS) {
  1265. (IpaLogEvent)(
  1266. Resource->ResourceHandle,
  1267. LOG_WARNING,
  1268. L"Failed to delete IP interface information from database, status %1!u!.\n",
  1269. status
  1270. );
  1271. }
  1272. }
  1273. }
  1274. //
  1275. // Tell the DNS resolver to update its list of local ip addresses.
  1276. //
  1277. // BUGBUG - The DNS resolver should do this automatically based
  1278. // on PnP events in the Whistler release. Remove this code
  1279. // after verifiying that functionality.
  1280. //
  1281. // This issue is tracked with bug 97134.
  1282. // DnsNotifyResolver(0, 0);
  1283. DnsNotifyResolverClusterIp((IP_ADDRESS)Resource->Address, FALSE);
  1284. }
  1285. return;
  1286. } // IpaValidateAndOfflineInterfaces
  1287. DWORD
  1288. IpaGetNodeParameters(
  1289. PIPA_RESOURCE Resource,
  1290. BOOL OkToCreate
  1291. )
  1292. /*++
  1293. Routine Description:
  1294. get any node based parameters from the registry. We can't call create
  1295. during IpaOpen so this won't do much for the first open of a new resource.
  1296. Arguments:
  1297. Resource - pointer to IP internal resource data block
  1298. OkToCreate - true if we can use ClusterRegCreateKey instead of
  1299. ClusterRegOpenKey
  1300. Return Value:
  1301. success if everything worked ok
  1302. --*/
  1303. {
  1304. DWORD status;
  1305. if (Resource->NodeParametersKey == NULL) {
  1306. //
  1307. // create or open the resource's node-specific parameters key.
  1308. //
  1309. if ( OkToCreate ) {
  1310. status = ClusterRegCreateKey(Resource->ParametersKey,
  1311. Resource->NodeId,
  1312. 0,
  1313. KEY_READ,
  1314. NULL,
  1315. &(Resource->NodeParametersKey),
  1316. NULL);
  1317. }
  1318. else {
  1319. status = ClusterRegOpenKey(Resource->ParametersKey,
  1320. Resource->NodeId,
  1321. KEY_READ,
  1322. &(Resource->NodeParametersKey));
  1323. }
  1324. if (status != NO_ERROR) {
  1325. (IpaLogEvent)(
  1326. Resource->ResourceHandle,
  1327. LOG_ERROR,
  1328. L"Unable to %1!ws! node parameters key, status %2!u!.\n",
  1329. OkToCreate ? L"create" : L"open",
  1330. status
  1331. );
  1332. if ( !OkToCreate ) {
  1333. //
  1334. // we still need to init some values in the resource data
  1335. // block if open fails
  1336. //
  1337. Resource->NteContext = INVALID_NTE_CONTEXT;
  1338. Resource->NteInstance = 0;
  1339. Resource->NbtDeviceName = NULL;
  1340. Resource->NbtDeviceInstance = 0;
  1341. }
  1342. return(status);
  1343. }
  1344. }
  1345. //
  1346. // Read the old TCP/IP and NBT parameters.
  1347. //
  1348. status = ResUtilGetDwordValue(
  1349. Resource->NodeParametersKey,
  1350. L"InterfaceContext",
  1351. &(Resource->NteContext),
  1352. INVALID_NTE_CONTEXT
  1353. );
  1354. if (status == ERROR_SUCCESS) {
  1355. status = ResUtilGetDwordValue(
  1356. Resource->NodeParametersKey,
  1357. L"InterfaceInstance",
  1358. &(Resource->NteInstance),
  1359. 0
  1360. );
  1361. if (status != ERROR_SUCCESS) {
  1362. Resource->NteContext = INVALID_NTE_CONTEXT;
  1363. }
  1364. }
  1365. Resource->NbtDeviceName = ResUtilGetSzValue(
  1366. Resource->NodeParametersKey,
  1367. L"NbtDeviceName"
  1368. );
  1369. if (Resource->NbtDeviceName != NULL) {
  1370. status = ResUtilGetDwordValue(
  1371. Resource->NodeParametersKey,
  1372. L"NbtDeviceInstance",
  1373. &(Resource->NbtDeviceInstance),
  1374. 0
  1375. );
  1376. if (status != ERROR_SUCCESS) {
  1377. LocalFree(Resource->NbtDeviceName);
  1378. Resource->NbtDeviceName = NULL;
  1379. }
  1380. }
  1381. return status;
  1382. }
  1383. DWORD
  1384. IpaInitializeInternalParameters(
  1385. PIPA_RESOURCE Resource
  1386. )
  1387. {
  1388. DWORD status;
  1389. ASSERT(Resource->ResourceKey != NULL);
  1390. ASSERT(Resource->ResourceHandle != NULL);
  1391. if (Resource->ParametersKey == NULL) {
  1392. //
  1393. // Open the resource's parameters key.
  1394. //
  1395. status = ClusterRegOpenKey(
  1396. Resource->ResourceKey,
  1397. CLUSREG_KEYNAME_PARAMETERS,
  1398. KEY_READ,
  1399. &(Resource->ParametersKey)
  1400. );
  1401. if (status != NO_ERROR) {
  1402. (IpaLogEvent)(
  1403. Resource->ResourceHandle,
  1404. LOG_ERROR,
  1405. L"Unable to open parameters key, status %1!u!.\n",
  1406. status
  1407. );
  1408. return(status);
  1409. }
  1410. }
  1411. if (Resource->NodeParametersKey == NULL) {
  1412. status = IpaGetNodeParameters( Resource, FALSE );
  1413. }
  1414. Resource->InternalParametersInitialized = TRUE;
  1415. return(ERROR_SUCCESS);
  1416. } // IpaInitializeInternalParameters
  1417. VOID
  1418. IpaFreePrivateProperties(
  1419. IN PIPA_PRIVATE_PROPS PrivateProps
  1420. )
  1421. {
  1422. if (PrivateProps->NetworkString != NULL) {
  1423. LocalFree(PrivateProps->NetworkString);
  1424. PrivateProps->NetworkString = NULL;
  1425. }
  1426. if (PrivateProps->AddressString != NULL) {
  1427. LocalFree(PrivateProps->AddressString);
  1428. PrivateProps->AddressString = NULL;
  1429. }
  1430. if (PrivateProps->SubnetMaskString != NULL) {
  1431. LocalFree(PrivateProps->SubnetMaskString);
  1432. PrivateProps->SubnetMaskString = NULL;
  1433. }
  1434. return;
  1435. } // IpaFreePrivateProperties
  1436. VOID
  1437. IpaFreeLocalParameters(
  1438. IN PIPA_LOCAL_PARAMS LocalParams
  1439. )
  1440. {
  1441. if (LocalParams->InterfaceId != NULL) {
  1442. LocalFree(LocalParams->InterfaceId);
  1443. LocalParams->InterfaceId = NULL;
  1444. }
  1445. if (LocalParams->InterfaceName != NULL) {
  1446. LocalFree(LocalParams->InterfaceName);
  1447. LocalParams->InterfaceName = NULL;
  1448. }
  1449. if (LocalParams->AdapterName != NULL) {
  1450. LocalFree(LocalParams->AdapterName);
  1451. LocalParams->AdapterName = NULL;
  1452. }
  1453. if (LocalParams->AdapterId != NULL) {
  1454. LocalFree(LocalParams->AdapterId);
  1455. LocalParams->AdapterId = NULL;
  1456. }
  1457. return;
  1458. } // IpaFreeLocalParameters
  1459. DWORD
  1460. IpaGetLocalParameters(
  1461. IN PIPA_RESOURCE Resource,
  1462. IN OUT PIPA_LOCAL_PARAMS LocalParams
  1463. )
  1464. /*++
  1465. Routine Description:
  1466. Reads the local parameters needed to bring an IP address resource online.
  1467. Arguments:
  1468. Resource - Resource structure for the resource.
  1469. LocalParams - A pointer to a structure to fill in with the new
  1470. local parameters.
  1471. Return Value:
  1472. ERROR_SUCCESS if the routine is successful.
  1473. A Win32 error code otherwise.
  1474. --*/
  1475. {
  1476. DWORD status;
  1477. DWORD valueType;
  1478. LPWSTR deviceName;
  1479. DWORD deviceNameLength;
  1480. HKEY interfaceKey = NULL;
  1481. WCHAR networkId[NETWORK_ID_LENGTH + 1];
  1482. WCHAR nodeId[MAX_NODE_ID_LENGTH];
  1483. DWORD i;
  1484. DWORD valueLength;
  1485. DWORD type;
  1486. DWORD interfaceIdSize = (NETINTERFACE_ID_LENGTH + 1 ) * sizeof(WCHAR);
  1487. ZeroMemory(LocalParams, sizeof(IPA_LOCAL_PARAMS));
  1488. LocalParams->InterfaceId = LocalAlloc(LMEM_FIXED, interfaceIdSize);
  1489. if (LocalParams->InterfaceId == NULL) {
  1490. (IpaLogEvent)(
  1491. Resource->ResourceHandle,
  1492. LOG_ERROR,
  1493. L"Open: Unable to allocate memory for netinterface ID.\n"
  1494. );
  1495. status = ERROR_NOT_ENOUGH_MEMORY;
  1496. goto error_exit;
  1497. }
  1498. //
  1499. // Enumerate the interface keys looking for the right one for this
  1500. // node/network.
  1501. //
  1502. for (i=0; ;i++) {
  1503. if (interfaceKey != NULL) {
  1504. ClusterRegCloseKey(interfaceKey); interfaceKey = NULL;
  1505. }
  1506. valueLength = interfaceIdSize;
  1507. status = ClusterRegEnumKey(
  1508. Resource->InterfacesKey,
  1509. i,
  1510. LocalParams->InterfaceId,
  1511. &valueLength,
  1512. NULL
  1513. );
  1514. if (status != ERROR_SUCCESS) {
  1515. if ( status == ERROR_NO_MORE_ITEMS ) {
  1516. status = ERROR_NETWORK_NOT_AVAILABLE;
  1517. }
  1518. (IpaLogEvent)(
  1519. Resource->ResourceHandle,
  1520. LOG_ERROR,
  1521. L"Open: Unable to find netinterface for node %1!ws! on network %2!ws!, status %3!u!.\n",
  1522. Resource->NodeId,
  1523. Resource->InternalPrivateProps.NetworkString,
  1524. status
  1525. );
  1526. goto error_exit;
  1527. }
  1528. //
  1529. // Open the enumerated interface key
  1530. //
  1531. status = ClusterRegOpenKey(
  1532. Resource->InterfacesKey,
  1533. LocalParams->InterfaceId,
  1534. KEY_READ,
  1535. &interfaceKey
  1536. );
  1537. if (status != ERROR_SUCCESS) {
  1538. (IpaLogEvent)(
  1539. Resource->ResourceHandle,
  1540. LOG_WARNING,
  1541. L"Open: Unable to open key for network interface %1!ws!, status %2!u!.\n",
  1542. LocalParams->InterfaceId,
  1543. status
  1544. );
  1545. continue;
  1546. }
  1547. //
  1548. // Read the node value.
  1549. //
  1550. valueLength = sizeof(nodeId);
  1551. status = ClusterRegQueryValue(
  1552. interfaceKey,
  1553. CLUSREG_NAME_NETIFACE_NODE,
  1554. &type,
  1555. (LPBYTE) &(nodeId[0]),
  1556. &valueLength
  1557. );
  1558. if ( status != ERROR_SUCCESS ) {
  1559. (IpaLogEvent)(
  1560. Resource->ResourceHandle,
  1561. LOG_WARNING,
  1562. L"Open: Unable to read node value for netinterface %1!ws!, status %2!u!.\n",
  1563. LocalParams->InterfaceId,
  1564. status
  1565. );
  1566. continue;
  1567. }
  1568. if (wcscmp(Resource->NodeId, nodeId) != 0) {
  1569. continue;
  1570. }
  1571. //
  1572. // Read the network value.
  1573. //
  1574. valueLength = sizeof(networkId);
  1575. status = ClusterRegQueryValue(
  1576. interfaceKey,
  1577. CLUSREG_NAME_NETIFACE_NETWORK,
  1578. &type,
  1579. (LPBYTE) &(networkId[0]),
  1580. &valueLength
  1581. );
  1582. if ( status != ERROR_SUCCESS ) {
  1583. (IpaLogEvent)(
  1584. Resource->ResourceHandle,
  1585. LOG_WARNING,
  1586. L"Open: Unable to read network value for netinterface %1!ws!, status %2!u!.\n",
  1587. LocalParams->InterfaceId,
  1588. status
  1589. );
  1590. continue;
  1591. }
  1592. if (wcscmp(
  1593. Resource->InternalPrivateProps.NetworkString,
  1594. networkId
  1595. ) == 0
  1596. )
  1597. {
  1598. //
  1599. // Found the right interface key.
  1600. //
  1601. break;
  1602. }
  1603. }
  1604. //
  1605. // Read the adapter name for the interface.
  1606. //
  1607. LocalParams->AdapterName = ResUtilGetSzValue(
  1608. interfaceKey,
  1609. CLUSREG_NAME_NETIFACE_ADAPTER_NAME
  1610. );
  1611. if (LocalParams->AdapterName == NULL) {
  1612. status = GetLastError();
  1613. (IpaLogEvent)(
  1614. Resource->ResourceHandle,
  1615. LOG_ERROR,
  1616. L"Open: Unable to read adapter name parameter for interface %1!ws!, status %2!u!.\n",
  1617. LocalParams->InterfaceId,
  1618. status
  1619. );
  1620. goto error_exit;
  1621. }
  1622. //
  1623. // Read the adapter Id for the interface.
  1624. //
  1625. LocalParams->AdapterId = ResUtilGetSzValue(
  1626. interfaceKey,
  1627. CLUSREG_NAME_NETIFACE_ADAPTER_ID
  1628. );
  1629. if (LocalParams->AdapterId == NULL) {
  1630. status = GetLastError();
  1631. (IpaLogEvent)(
  1632. Resource->ResourceHandle,
  1633. LOG_ERROR,
  1634. L"Open: Unable to read adapter Id parameter for interface %1!ws!, status %2!u!.\n",
  1635. LocalParams->InterfaceId,
  1636. status
  1637. );
  1638. goto error_exit;
  1639. }
  1640. LocalParams->InterfaceName = ResUtilGetSzValue(
  1641. interfaceKey,
  1642. CLUSREG_NAME_NETIFACE_NAME
  1643. );
  1644. if (LocalParams->InterfaceName == NULL) {
  1645. status = GetLastError();
  1646. (IpaLogEvent)(
  1647. Resource->ResourceHandle,
  1648. LOG_ERROR,
  1649. L"Open: Unable to read name for netinterface %1!ws!, status %2!u!.\n",
  1650. LocalParams->InterfaceId,
  1651. status
  1652. );
  1653. goto error_exit;
  1654. }
  1655. ClusterRegCloseKey(interfaceKey); interfaceKey = NULL;
  1656. //
  1657. // Get the WINS addresses for this interface.
  1658. //
  1659. deviceNameLength = sizeof(WCHAR) * ( lstrlenW(NbtDevicePrefix) +
  1660. lstrlenW(LocalParams->AdapterId) +
  1661. lstrlenW(NbtDeviceSuffix) + 1
  1662. );
  1663. deviceName = LocalAlloc(LMEM_FIXED, deviceNameLength);
  1664. if (deviceName == NULL) {
  1665. status = ERROR_NOT_ENOUGH_MEMORY;
  1666. (IpaLogEvent)(
  1667. Resource->ResourceHandle,
  1668. LOG_ERROR,
  1669. L"Unable to allocate memory for NBT device name.\n"
  1670. );
  1671. goto error_exit;
  1672. }
  1673. lstrcpyW(deviceName, NbtDevicePrefix);
  1674. lstrcatW(deviceName, LocalParams->AdapterId);
  1675. lstrcatW(deviceName, NbtDeviceSuffix);
  1676. status = NbtGetWinsAddresses(
  1677. deviceName,
  1678. &(LocalParams->NbtPrimaryWinsAddress),
  1679. &(LocalParams->NbtSecondaryWinsAddress)
  1680. );
  1681. LocalFree(deviceName);
  1682. if (status != ERROR_SUCCESS) {
  1683. (IpaLogEvent)(
  1684. Resource->ResourceHandle,
  1685. LOG_WARNING,
  1686. L"Unable to determine WINS server addresses for adapter %1!ws!, status %2!u!\n",
  1687. LocalParams->AdapterName,
  1688. status
  1689. );
  1690. //
  1691. // NBT sets the WINS server addresses to loopback by default.
  1692. //
  1693. LocalParams->NbtPrimaryWinsAddress = inet_addr("127.0.0.1");
  1694. LocalParams->NbtSecondaryWinsAddress =
  1695. LocalParams->NbtPrimaryWinsAddress;
  1696. }
  1697. status = ERROR_SUCCESS;
  1698. error_exit:
  1699. if (interfaceKey != NULL) {
  1700. ClusterRegCloseKey(interfaceKey);
  1701. }
  1702. if (status != ERROR_SUCCESS) {
  1703. IpaFreeLocalParameters(LocalParams);
  1704. }
  1705. return(status);
  1706. } // IpaGetLocalParameters
  1707. //
  1708. // Primary Resource Functions
  1709. //
  1710. BOOLEAN
  1711. WINAPI
  1712. IpAddrDllEntryPoint(
  1713. IN HINSTANCE DllHandle,
  1714. IN DWORD Reason,
  1715. IN LPVOID Reserved
  1716. )
  1717. {
  1718. switch(Reason) {
  1719. case DLL_PROCESS_ATTACH:
  1720. return(IpaInit());
  1721. break;
  1722. case DLL_PROCESS_DETACH:
  1723. IpaCleanup();
  1724. break;
  1725. default:
  1726. break;
  1727. }
  1728. return(TRUE);
  1729. }
  1730. RESID
  1731. WINAPI
  1732. IpaOpen(
  1733. IN LPCWSTR ResourceName,
  1734. IN HKEY ResourceKey,
  1735. IN RESOURCE_HANDLE ResourceHandle
  1736. )
  1737. /*++
  1738. Routine Description:
  1739. Open routine for IP Address resource
  1740. Arguments:
  1741. ResourceName - supplies the resource name
  1742. ResourceKey - a registry key for access registry information for this
  1743. resource.
  1744. ResourceHandle - the resource handle to be supplied with SetResourceStatus
  1745. is called.
  1746. Return Value:
  1747. RESID of created resource
  1748. NULL on failure
  1749. --*/
  1750. {
  1751. DWORD status;
  1752. PIPA_RESOURCE resource = NULL;
  1753. DWORD nodeIdSize = MAX_NODE_ID_LENGTH + 1;
  1754. HKEY clusterKey = NULL;
  1755. IpaAcquireGlobalLock();
  1756. if (IpaOpenResourceCount == 0) {
  1757. ASSERT(IpaClusterHandle == NULL);
  1758. IpaClusterHandle = OpenCluster(NULL);
  1759. if (IpaClusterHandle == NULL) {
  1760. status = GetLastError();
  1761. IpaReleaseGlobalLock();
  1762. (IpaLogEvent)(
  1763. ResourceHandle,
  1764. LOG_ERROR,
  1765. L"Unable to open cluster handle, status %1!u!.\n",
  1766. status
  1767. );
  1768. return(0);
  1769. }
  1770. }
  1771. IpaOpenResourceCount++;
  1772. IpaReleaseGlobalLock();
  1773. resource = LocalAlloc(
  1774. (LMEM_FIXED | LMEM_ZEROINIT),
  1775. sizeof(IPA_RESOURCE)
  1776. );
  1777. if (resource == NULL) {
  1778. (IpaLogEvent)(
  1779. ResourceHandle,
  1780. LOG_ERROR,
  1781. L"Resource allocation failed.\n"
  1782. );
  1783. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1784. return(0);
  1785. }
  1786. //
  1787. // Initialize known fields.
  1788. //
  1789. InitializeCriticalSection(&(resource->Lock));
  1790. resource->ResourceHandle = ResourceHandle;
  1791. resource->State = ClusterResourceOffline;
  1792. resource->NteContext = INVALID_NTE_CONTEXT;
  1793. //
  1794. // Initialize the Linkage field as a list head. This
  1795. // prevents an AV in IpaClose if IpaOpen fails before
  1796. // the resource is added to IpaResourceList.
  1797. //
  1798. InitializeListHead(&(resource->Linkage));
  1799. //
  1800. // Allocate an address string buffer.
  1801. //
  1802. resource->InternalPrivateProps.AddressString =
  1803. LocalAlloc(
  1804. LMEM_FIXED,
  1805. ( (IpaMaxIpAddressStringLength + 1) *
  1806. sizeof(WCHAR)
  1807. ));
  1808. if (resource->InternalPrivateProps.AddressString == NULL) {
  1809. (IpaLogEvent)(
  1810. ResourceHandle,
  1811. LOG_ERROR,
  1812. L"Resource allocation failed.\n"
  1813. );
  1814. status = ERROR_NOT_ENOUGH_MEMORY;
  1815. goto error_exit;
  1816. }
  1817. lstrcpyW(resource->InternalPrivateProps.AddressString, L"[Unknown]");
  1818. //
  1819. // Figure out what node we're running on.
  1820. //
  1821. status = GetCurrentClusterNodeId(
  1822. &(resource->NodeId[0]),
  1823. &nodeIdSize
  1824. );
  1825. if ( status != ERROR_SUCCESS ) {
  1826. status = GetLastError();
  1827. (IpaLogEvent)(
  1828. ResourceHandle,
  1829. LOG_ERROR,
  1830. L"Unable to get local node ID, status %1!u!.\n",
  1831. status
  1832. );
  1833. goto error_exit;
  1834. }
  1835. //
  1836. // Open a private handle to our resource key so that we can get our
  1837. // name later if we need to log an event.
  1838. //
  1839. status = ClusterRegOpenKey(
  1840. ResourceKey,
  1841. L"",
  1842. KEY_READ,
  1843. &(resource->ResourceKey)
  1844. );
  1845. if (status != ERROR_SUCCESS) {
  1846. (IpaLogEvent)(
  1847. ResourceHandle,
  1848. LOG_ERROR,
  1849. L"Unable to open resource key. Error: %1!u!.\n",
  1850. status
  1851. );
  1852. goto error_exit;
  1853. }
  1854. //
  1855. // Open a key to the networks portion of the cluster registry.
  1856. //
  1857. clusterKey = GetClusterKey(IpaClusterHandle, KEY_READ);
  1858. if (clusterKey == NULL) {
  1859. status = GetLastError();
  1860. (IpaLogEvent)(
  1861. ResourceHandle,
  1862. LOG_ERROR,
  1863. L"Unable to open cluster registry key, status %1!u!.\n",
  1864. status
  1865. );
  1866. goto error_exit;
  1867. }
  1868. status = ClusterRegOpenKey(
  1869. clusterKey,
  1870. L"Networks",
  1871. KEY_READ,
  1872. &(resource->NetworksKey)
  1873. );
  1874. if (status != ERROR_SUCCESS) {
  1875. (IpaLogEvent)(
  1876. ResourceHandle,
  1877. LOG_ERROR,
  1878. L"Unable to open networks registry key, status %1!u!.\n",
  1879. status
  1880. );
  1881. goto error_exit;
  1882. }
  1883. //
  1884. // Open a key to the interfaces portion of the cluster registry.
  1885. //
  1886. status = ClusterRegOpenKey(
  1887. clusterKey,
  1888. L"NetworkInterfaces",
  1889. KEY_READ,
  1890. &(resource->InterfacesKey)
  1891. );
  1892. if (status != ERROR_SUCCESS) {
  1893. (IpaLogEvent)(
  1894. ResourceHandle,
  1895. LOG_ERROR,
  1896. L"Unable to open network interfaces registry key, status %1!u!.\n",
  1897. status
  1898. );
  1899. goto error_exit;
  1900. }
  1901. ClusterRegCloseKey(clusterKey); clusterKey = NULL;
  1902. status = IpaInitializeInternalParameters(resource);
  1903. if (status == ERROR_SUCCESS) {
  1904. //
  1905. // Validate our TCP/IP and NBT parameters and clean up any old
  1906. // interfaces we left hanging around from the last run.
  1907. //
  1908. IpaValidateAndOfflineInterfaces(resource);
  1909. }
  1910. //
  1911. // Link the resource onto the global list.
  1912. //
  1913. IpaAcquireGlobalLock();
  1914. InsertTailList(&IpaResourceList, &(resource->Linkage));
  1915. IpaReleaseGlobalLock();
  1916. (IpaLogEvent)(
  1917. ResourceHandle,
  1918. LOG_INFORMATION,
  1919. L"Resource open, resource ID = %1!u!.\n",
  1920. resource
  1921. );
  1922. return(resource);
  1923. error_exit:
  1924. IpaClose((RESID) resource);
  1925. if (clusterKey != NULL) {
  1926. ClusterRegCloseKey(clusterKey);
  1927. }
  1928. SetLastError( status );
  1929. return(0);
  1930. } // IpaOpen
  1931. VOID
  1932. WINAPI
  1933. IpaDoOfflineProcessing(
  1934. IN PIPA_RESOURCE Resource,
  1935. IN RESOURCE_STATUS * ResourceStatus
  1936. )
  1937. /*++
  1938. Routine Description:
  1939. Final offline processing for IP Address resource.
  1940. Arguments:
  1941. Resource - supplies the resource it to be taken offline
  1942. Return Value:
  1943. None.
  1944. Notes:
  1945. Called with the resource lock held.
  1946. Returns with the resource lock released.
  1947. --*/
  1948. {
  1949. DWORD status = ERROR_SUCCESS;
  1950. ULONG address = 0, mask = 0;
  1951. HNETINTERFACE ifHandle;
  1952. ASSERT(Resource->State == ClusterResourceOfflinePending);
  1953. IpaValidateAndOfflineInterfaces(Resource);
  1954. //
  1955. // Make local copies of external resource handles
  1956. //
  1957. ifHandle = Resource->InterfaceHandle;
  1958. Resource->InterfaceHandle = NULL;
  1959. Resource->State = ClusterResourceOffline;
  1960. if (ResourceStatus != NULL) {
  1961. ResourceStatus->CheckPoint++;
  1962. ResourceStatus->ResourceState = ClusterResourceOffline;
  1963. (IpaSetResourceStatus)(Resource->ResourceHandle, ResourceStatus);
  1964. }
  1965. (IpaLogEvent)(
  1966. Resource->ResourceHandle,
  1967. LOG_INFORMATION,
  1968. L"Address %1!ws! on adapter %2!ws! offline.\n",
  1969. Resource->InternalPrivateProps.AddressString,
  1970. ( (Resource->LocalParams.AdapterName != NULL) ?
  1971. Resource->LocalParams.AdapterName : L"[Unknown]"
  1972. ));
  1973. IpaReleaseResourceLock(Resource);
  1974. //
  1975. // Free external resources.
  1976. //
  1977. if (ifHandle != NULL) {
  1978. CloseClusterNetInterface(ifHandle);
  1979. }
  1980. IpaAcquireGlobalLock();
  1981. //
  1982. // If this is the last resource, cleanup the global state.
  1983. //
  1984. ASSERT(IpaOnlineResourceCount > 0);
  1985. if (--IpaOnlineResourceCount == 0) {
  1986. IpaLastOfflineCleanup();
  1987. //
  1988. // The lock was released.
  1989. //
  1990. }
  1991. else {
  1992. IpaReleaseGlobalLock();
  1993. }
  1994. return;
  1995. } // IpaDoOfflineProcessing
  1996. VOID
  1997. WINAPI
  1998. IpaInternalOffline(
  1999. IN PIPA_RESOURCE Resource
  2000. )
  2001. /*++
  2002. Routine Description:
  2003. Internal offline routine for IP Address resource.
  2004. Arguments:
  2005. Resource - supplies the resource it to be taken offline
  2006. Return Value:
  2007. None.
  2008. --*/
  2009. {
  2010. //
  2011. // Terminate the online thread, if it is running.
  2012. //
  2013. ClusWorkerTerminate(&(Resource->OnlineThread));
  2014. //
  2015. // Synchronize IpaOffline, IpaTerminate, and IpaWorkerThread.
  2016. //
  2017. IpaAcquireResourceLock(Resource);
  2018. if (Resource->State == ClusterResourceOffline) {
  2019. (IpaLogEvent)(
  2020. Resource->ResourceHandle,
  2021. LOG_INFORMATION,
  2022. L"Resource is already offline.\n"
  2023. );
  2024. IpaReleaseResourceLock(Resource);
  2025. return;
  2026. }
  2027. Resource->State = ClusterResourceOfflinePending;
  2028. IpaDoOfflineProcessing(Resource, NULL);
  2029. //
  2030. // The lock was released.
  2031. //
  2032. return;
  2033. } // IpaInternalOffline
  2034. DWORD
  2035. WINAPI
  2036. IpaOffline(
  2037. IN RESID Resource
  2038. )
  2039. /*++
  2040. Routine Description:
  2041. Offline routine for IP Address resource.
  2042. Arguments:
  2043. Resource - supplies resource id to be taken offline.
  2044. Return Value:
  2045. ERROR_SUCCESS if successful.
  2046. A Win32 error code otherwise.
  2047. --*/
  2048. {
  2049. DWORD status;
  2050. PIPA_RESOURCE resource = (PIPA_RESOURCE) Resource;
  2051. if (resource != NULL) {
  2052. (IpaLogEvent)(
  2053. resource->ResourceHandle,
  2054. LOG_INFORMATION,
  2055. L"Taking resource offline...\n"
  2056. );
  2057. IpaInternalOffline(resource);
  2058. status = ERROR_SUCCESS;
  2059. }
  2060. else {
  2061. status = ERROR_RESOURCE_NOT_FOUND;
  2062. }
  2063. return(status);
  2064. } // IpaOffline
  2065. VOID
  2066. WINAPI
  2067. IpaTerminate(
  2068. IN RESID Resource
  2069. )
  2070. /*++
  2071. Routine Description:
  2072. Terminate routine for IP Address resource.
  2073. Arguments:
  2074. Resource - supplies resource id to be terminated
  2075. Return Value:
  2076. None.
  2077. --*/
  2078. {
  2079. PIPA_RESOURCE resource = (PIPA_RESOURCE) Resource;
  2080. if (resource != NULL) {
  2081. (IpaLogEvent)(
  2082. resource->ResourceHandle,
  2083. LOG_INFORMATION,
  2084. L"Terminating resource...\n"
  2085. );
  2086. IpaInternalOffline(resource);
  2087. }
  2088. return;
  2089. } // IpaTerminate
  2090. DWORD
  2091. IpaOnlineThread(
  2092. IN PCLUS_WORKER pWorker,
  2093. IN PIPA_RESOURCE Resource
  2094. )
  2095. /*++
  2096. Routine Description:
  2097. Brings an IP address resource online.
  2098. Arguments:
  2099. pWorker - Supplies the worker structure
  2100. Resource - A pointer to the IPA_RESOURCE block for this resource.
  2101. Returns:
  2102. ERROR_SUCCESS if successful.
  2103. Win32 error code on failure.
  2104. --*/
  2105. {
  2106. DWORD status = ERROR_SUCCESS;
  2107. DWORD i;
  2108. RESOURCE_EXIT_STATE exit;
  2109. RESOURCE_STATUS resourceStatus;
  2110. BOOL retried;
  2111. IPA_LOCAL_PARAMS newParams;
  2112. PIPA_LOCAL_PARAMS localParams = NULL;
  2113. PIPA_PRIVATE_PROPS privateProps = NULL;
  2114. LPWSTR nameOfPropInError = NULL;
  2115. CLUSTER_NETINTERFACE_STATE state;
  2116. BOOL firstOnline = FALSE;
  2117. DWORD numTries;
  2118. ZeroMemory(&newParams, sizeof(newParams));
  2119. (IpaLogEvent)(
  2120. Resource->ResourceHandle,
  2121. LOG_INFORMATION,
  2122. L"Online thread running.\n",
  2123. Resource
  2124. );
  2125. IpaAcquireGlobalLock();
  2126. IpaAcquireResourceLock(Resource);
  2127. if (IpaOnlineResourceCount++ == 0) {
  2128. firstOnline = TRUE;
  2129. }
  2130. ResUtilInitializeResourceStatus(&resourceStatus);
  2131. resourceStatus.CheckPoint = 1;
  2132. resourceStatus.ResourceState = ClusterResourceOnlinePending;
  2133. exit = (IpaSetResourceStatus)(Resource->ResourceHandle, &resourceStatus);
  2134. if ( exit == ResourceExitStateTerminate ) {
  2135. IpaReleaseGlobalLock();
  2136. (IpaLogEvent)(
  2137. Resource->ResourceHandle,
  2138. LOG_ERROR,
  2139. L"Online thread aborted.\n"
  2140. );
  2141. status = ERROR_OPERATION_ABORTED;
  2142. goto error_exit;
  2143. }
  2144. //
  2145. // If this is the first resource to go online in this process,
  2146. // initialize the global state.
  2147. //
  2148. if (firstOnline) {
  2149. status = IpaFirstOnlineInit(Resource->ResourceHandle);
  2150. //
  2151. // The global lock was released.
  2152. //
  2153. if (status != ERROR_SUCCESS) {
  2154. goto error_exit;
  2155. }
  2156. }
  2157. else {
  2158. IpaReleaseGlobalLock();
  2159. }
  2160. resourceStatus.CheckPoint++;
  2161. exit = (IpaSetResourceStatus)(Resource->ResourceHandle, &resourceStatus);
  2162. if ( exit == ResourceExitStateTerminate ) {
  2163. (IpaLogEvent)(
  2164. Resource->ResourceHandle,
  2165. LOG_ERROR,
  2166. L"Online thread aborted.\n"
  2167. );
  2168. status = ERROR_OPERATION_ABORTED;
  2169. goto error_exit;
  2170. }
  2171. //
  2172. // Check to see if the online operation was aborted while this thread
  2173. // was starting up.
  2174. //
  2175. if (ClusWorkerCheckTerminate(pWorker)) {
  2176. status = ERROR_OPERATION_ABORTED;
  2177. Resource->State = ClusterResourceOfflinePending;
  2178. goto error_exit;
  2179. }
  2180. if (!Resource->InternalParametersInitialized) {
  2181. status = IpaInitializeInternalParameters(Resource);
  2182. if (status != ERROR_SUCCESS) {
  2183. goto error_exit;
  2184. }
  2185. }
  2186. else {
  2187. status = IpaGetNodeParameters( Resource, TRUE );
  2188. }
  2189. //
  2190. // Make sure the old interfaces are valid and offline.
  2191. //
  2192. IpaValidateAndOfflineInterfaces(Resource);
  2193. //
  2194. // Read and verify the resource's private properties.
  2195. //
  2196. privateProps = &(Resource->InternalPrivateProps);
  2197. status = ResUtilGetPropertiesToParameterBlock(
  2198. Resource->ParametersKey,
  2199. IpaResourcePrivateProperties,
  2200. (LPBYTE) privateProps,
  2201. TRUE, // CheckForRequiredProperties
  2202. &nameOfPropInError
  2203. );
  2204. if (status != ERROR_SUCCESS) {
  2205. (IpaLogEvent)(
  2206. Resource->ResourceHandle,
  2207. LOG_ERROR,
  2208. L"Unable to read the '%1' property. Error: %2!u!.\n",
  2209. (nameOfPropInError == NULL ? L"" : nameOfPropInError),
  2210. status
  2211. );
  2212. goto error_exit;
  2213. }
  2214. Resource->EnableNetbios = privateProps->EnableNetbios;
  2215. //
  2216. // Convert the address and subnet mask strings to binary.
  2217. //
  2218. status = ClRtlTcpipStringToAddress(
  2219. privateProps->AddressString,
  2220. &(Resource->Address)
  2221. );
  2222. if (status != ERROR_SUCCESS) {
  2223. status = ERROR_INVALID_PARAMETER;
  2224. ClusResLogSystemEventByKeyData(
  2225. Resource->ResourceKey,
  2226. LOG_CRITICAL,
  2227. RES_IPADDR_INVALID_ADDRESS,
  2228. sizeof(Resource->Address),
  2229. &(Resource->Address)
  2230. );
  2231. (IpaLogEvent)(
  2232. Resource->ResourceHandle,
  2233. LOG_ERROR,
  2234. L"Invalid address %1!ws!.\n",
  2235. privateProps->AddressString
  2236. );
  2237. goto error_exit;
  2238. }
  2239. status = ClRtlTcpipStringToAddress(
  2240. privateProps->SubnetMaskString,
  2241. &(Resource->SubnetMask)
  2242. );
  2243. if (status != ERROR_SUCCESS) {
  2244. status = ERROR_INVALID_PARAMETER;
  2245. ClusResLogSystemEventByKeyData(
  2246. Resource->ResourceKey,
  2247. LOG_CRITICAL,
  2248. RES_IPADDR_INVALID_SUBNET,
  2249. sizeof(Resource->SubnetMask),
  2250. &(Resource->SubnetMask)
  2251. );
  2252. (IpaLogEvent)(
  2253. Resource->ResourceHandle,
  2254. LOG_ERROR,
  2255. L"Invalid subnet mask %1!ws!.\n",
  2256. privateProps->SubnetMaskString
  2257. );
  2258. goto error_exit;
  2259. }
  2260. status = IpaPatchNetworkGuidIfNecessary(Resource, privateProps);
  2261. if (status != ERROR_SUCCESS) {
  2262. (IpaLogEvent)(
  2263. Resource->ResourceHandle,
  2264. LOG_WARNING,
  2265. L"IpaPatchNetworkGuidIfNecessary failed, status %1!d!.\n",
  2266. status
  2267. );
  2268. }
  2269. //
  2270. // Fetch the resource's parameters for the local node.
  2271. //
  2272. status = IpaGetLocalParameters(Resource, &newParams);
  2273. if (status != ERROR_SUCCESS) {
  2274. goto error_exit;
  2275. }
  2276. localParams = &(Resource->LocalParams);
  2277. //
  2278. // Update the interface name.
  2279. //
  2280. if (localParams->InterfaceName != NULL) {
  2281. LocalFree(localParams->InterfaceName);
  2282. }
  2283. localParams->InterfaceName = newParams.InterfaceName;
  2284. newParams.InterfaceName = NULL;
  2285. //
  2286. // Update the interface ID.
  2287. //
  2288. if ( (localParams->InterfaceId != NULL) &&
  2289. (lstrcmp(localParams->InterfaceId, newParams.InterfaceId) != 0)
  2290. )
  2291. {
  2292. LocalFree(localParams->InterfaceId);
  2293. localParams->InterfaceId = NULL;
  2294. if (Resource->InterfaceHandle != NULL) {
  2295. CloseClusterNetInterface(Resource->InterfaceHandle);
  2296. Resource->InterfaceHandle = NULL;
  2297. }
  2298. }
  2299. if (localParams->InterfaceId == NULL) {
  2300. localParams->InterfaceId = newParams.InterfaceId;
  2301. newParams.InterfaceId = NULL;
  2302. }
  2303. //
  2304. // Update the interface handle.
  2305. //
  2306. if (Resource->InterfaceHandle == NULL) {
  2307. Resource->InterfaceHandle = OpenClusterNetInterface(
  2308. IpaClusterHandle,
  2309. localParams->InterfaceName
  2310. );
  2311. if (Resource->InterfaceHandle == NULL) {
  2312. status = GetLastError();
  2313. (IpaLogEvent)(
  2314. Resource->ResourceHandle,
  2315. LOG_ERROR,
  2316. L"Online: Unable to open object for netinterface %1!ws!, status %2!u!.\n",
  2317. localParams->InterfaceId,
  2318. status
  2319. );
  2320. goto error_exit;
  2321. }
  2322. else {
  2323. (IpaLogEvent)(
  2324. Resource->ResourceHandle,
  2325. LOG_INFORMATION,
  2326. L"Online: Opened object handle for netinterface %1!ws!.\n",
  2327. localParams->InterfaceId
  2328. );
  2329. }
  2330. }
  2331. //
  2332. // Register for state change notifications for the interface.
  2333. //
  2334. status = RegisterClusterNotify(
  2335. IpaClusterNotifyHandle,
  2336. ( CLUSTER_CHANGE_NETINTERFACE_STATE |
  2337. CLUSTER_CHANGE_NETINTERFACE_DELETED
  2338. ),
  2339. Resource->InterfaceHandle,
  2340. (DWORD_PTR) Resource
  2341. );
  2342. if (status != ERROR_SUCCESS) {
  2343. (IpaLogEvent)(
  2344. Resource->ResourceHandle,
  2345. LOG_ERROR,
  2346. L"Online: Unable to register notification for netinterface %1!ws!, status %2!u!.\n",
  2347. localParams->InterfaceId,
  2348. status
  2349. );
  2350. goto error_exit;
  2351. }
  2352. else {
  2353. (IpaLogEvent)(
  2354. Resource->ResourceHandle,
  2355. LOG_INFORMATION,
  2356. L"Online: Registered notification for netinterface %1!ws!.\n",
  2357. localParams->InterfaceId
  2358. );
  2359. }
  2360. //
  2361. // Check if the interface has failed already. We will sleep for a while
  2362. // and retry under certain conditions. The network state can take a few
  2363. // seconds to settle.
  2364. //
  2365. numTries = 0;
  2366. for (;;) {
  2367. resourceStatus.CheckPoint++;
  2368. exit = (IpaSetResourceStatus)(
  2369. Resource->ResourceHandle,
  2370. &resourceStatus
  2371. );
  2372. if ( exit == ResourceExitStateTerminate ) {
  2373. (IpaLogEvent)(
  2374. Resource->ResourceHandle,
  2375. LOG_ERROR,
  2376. L"Online thread aborted.\n"
  2377. );
  2378. status = ERROR_OPERATION_ABORTED;
  2379. goto error_exit;
  2380. }
  2381. state = GetClusterNetInterfaceState(
  2382. Resource->InterfaceHandle
  2383. );
  2384. if (state == ClusterNetInterfaceUp) {
  2385. break;
  2386. }
  2387. else if (state == ClusterNetInterfaceUnavailable ||
  2388. state == ClusterNetInterfaceUnreachable )
  2389. {
  2390. PWCHAR stateName = ( state == ClusterNetInterfaceUnavailable ?
  2391. L"available" : L"reachable" );
  2392. if (++numTries <= 5) {
  2393. (IpaLogEvent)(
  2394. Resource->ResourceHandle,
  2395. LOG_WARNING,
  2396. L"NetInterface %1!ws! is not %2!ws!. Wait & retry.\n",
  2397. Resource->LocalParams.InterfaceId,
  2398. stateName
  2399. );
  2400. Sleep(1000);
  2401. continue;
  2402. }
  2403. else {
  2404. status = ERROR_IO_DEVICE;
  2405. (IpaLogEvent)(
  2406. Resource->ResourceHandle,
  2407. LOG_ERROR,
  2408. L"Timed out waiting for NetInterface %1!ws! to be available. Failing resource.\n",
  2409. Resource->LocalParams.InterfaceId
  2410. );
  2411. goto error_exit;
  2412. }
  2413. }
  2414. else if (state == ClusterNetInterfaceFailed) {
  2415. status = ERROR_IO_DEVICE;
  2416. (IpaLogEvent)(
  2417. Resource->ResourceHandle,
  2418. LOG_ERROR,
  2419. L"NetInterface %1!ws! has failed.\n",
  2420. Resource->LocalParams.InterfaceId
  2421. );
  2422. goto error_exit;
  2423. }
  2424. else if (state == ClusterNetInterfaceStateUnknown) {
  2425. status = GetLastError();
  2426. (IpaLogEvent)(
  2427. Resource->ResourceHandle,
  2428. LOG_ERROR,
  2429. L"Failed to get state for netinterface %1!ws!, status %2!u!.\n",
  2430. Resource->LocalParams.InterfaceId,
  2431. status
  2432. );
  2433. goto error_exit;
  2434. }
  2435. else {
  2436. ASSERT(FALSE);
  2437. (IpaLogEvent)(
  2438. Resource->ResourceHandle,
  2439. LOG_ERROR,
  2440. L"Unrecognized state for netinterface %1!ws!, state %2!u!.\n",
  2441. Resource->LocalParams.InterfaceId,
  2442. state
  2443. );
  2444. status = ERROR_INVALID_PARAMETER;
  2445. goto error_exit;
  2446. }
  2447. }
  2448. Resource->FailureStatus = ERROR_SUCCESS;
  2449. //
  2450. // Update the adapter name parameter.
  2451. //
  2452. if (localParams->AdapterName != NULL) {
  2453. LocalFree(localParams->AdapterName);
  2454. }
  2455. localParams->AdapterName = newParams.AdapterName;
  2456. newParams.AdapterName = NULL;
  2457. //
  2458. // Update the adapter Id parameter.
  2459. //
  2460. if ((localParams->AdapterId == NULL) ||
  2461. (lstrcmpiW(localParams->AdapterId, newParams.AdapterId) != 0)) {
  2462. if (localParams->AdapterId != NULL) {
  2463. LocalFree(localParams->AdapterId);
  2464. }
  2465. localParams->AdapterId = newParams.AdapterId;
  2466. newParams.AdapterId = NULL;
  2467. if (Resource->NteContext != INVALID_NTE_CONTEXT) {
  2468. //
  2469. // Delete the old NTE.
  2470. //
  2471. (IpaLogEvent)(
  2472. Resource->ResourceHandle,
  2473. LOG_INFORMATION,
  2474. L"Adapter Id has changed to %1!ws!.\n",
  2475. localParams->AdapterId
  2476. );
  2477. IpaDeleteNte(
  2478. &(Resource->NteContext),
  2479. Resource->NodeParametersKey,
  2480. Resource->ResourceHandle
  2481. );
  2482. }
  2483. }
  2484. //
  2485. // Create a new NTE if we need one.
  2486. //
  2487. if (Resource->NteContext == INVALID_NTE_CONTEXT) {
  2488. status = IpaCreateNte(
  2489. localParams->AdapterId,
  2490. Resource->NodeParametersKey,
  2491. Resource->ResourceHandle,
  2492. &(Resource->NteContext),
  2493. &(Resource->NteInstance)
  2494. );
  2495. if (status != ERROR_SUCCESS) {
  2496. ClusResLogSystemEventByKeyData(
  2497. Resource->ResourceKey,
  2498. LOG_CRITICAL,
  2499. RES_IPADDR_NTE_CREATE_FAILED,
  2500. sizeof(status),
  2501. &status
  2502. );
  2503. (IpaLogEvent)(
  2504. Resource->ResourceHandle,
  2505. LOG_ERROR,
  2506. L"Failed to created new IP interface, status %1!u!.\n",
  2507. status
  2508. );
  2509. goto error_exit;
  2510. }
  2511. }
  2512. //
  2513. // Create a new NBT interface if we need one.
  2514. //
  2515. if (privateProps->EnableNetbios) {
  2516. if (Resource->NbtDeviceName == NULL) {
  2517. status = IpaCreateNbtInterface(
  2518. Resource->NodeParametersKey,
  2519. Resource->ResourceHandle,
  2520. &(Resource->NbtDeviceName),
  2521. &(Resource->NbtDeviceInstance)
  2522. );
  2523. if (status != ERROR_SUCCESS) {
  2524. ClusResLogSystemEventByKeyData(
  2525. Resource->ResourceKey,
  2526. LOG_CRITICAL,
  2527. RES_IPADDR_NBT_INTERFACE_CREATE_FAILED,
  2528. sizeof(status),
  2529. &status
  2530. );
  2531. (IpaLogEvent)(
  2532. Resource->ResourceHandle,
  2533. LOG_ERROR,
  2534. L"Failed to created new NBT interface, status %1!u!.\n",
  2535. status
  2536. );
  2537. goto error_exit;
  2538. }
  2539. }
  2540. }
  2541. else {
  2542. if (Resource->NbtDeviceName != NULL) {
  2543. IpaDeleteNbtInterface(
  2544. &(Resource->NbtDeviceName),
  2545. Resource->NodeParametersKey,
  2546. Resource->ResourceHandle
  2547. );
  2548. }
  2549. }
  2550. //
  2551. // Update the resource's WINS parameters
  2552. //
  2553. localParams->NbtPrimaryWinsAddress = newParams.NbtPrimaryWinsAddress;
  2554. localParams->NbtSecondaryWinsAddress = newParams.NbtSecondaryWinsAddress;
  2555. //
  2556. // We have valid, offline interfaces to work with. Send out a few ICMP
  2557. // Echo requests to see if any other machine has this address online.
  2558. // If one does, we'll abort this online operation.
  2559. //
  2560. resourceStatus.CheckPoint++;
  2561. exit = (IpaSetResourceStatus)(Resource->ResourceHandle, &resourceStatus);
  2562. if ( exit == ResourceExitStateTerminate ) {
  2563. (IpaLogEvent)(
  2564. Resource->ResourceHandle,
  2565. LOG_ERROR,
  2566. L"Online thread aborted.\n"
  2567. );
  2568. status = ERROR_OPERATION_ABORTED;
  2569. goto error_exit;
  2570. }
  2571. retried = FALSE;
  2572. while (TRUE) {
  2573. status = TcpipSetNTEAddress(
  2574. Resource->NteContext,
  2575. Resource->Address,
  2576. Resource->SubnetMask
  2577. );
  2578. if(status == ERROR_SUCCESS)
  2579. break;
  2580. if (!retried ) {
  2581. //
  2582. // Check to see if the online operation was aborted while
  2583. // this thread was blocked.
  2584. //
  2585. if (ClusWorkerCheckTerminate(pWorker)) {
  2586. status = ERROR_OPERATION_ABORTED;
  2587. Resource->State = ClusterResourceOfflinePending;
  2588. goto error_exit;
  2589. }
  2590. //
  2591. // Wait 5 secs to give the holder of the address a
  2592. // chance to let go
  2593. //
  2594. Sleep(5000);
  2595. //
  2596. // Check to see if the online operation was aborted while
  2597. // this thread was blocked.
  2598. //
  2599. if (ClusWorkerCheckTerminate(pWorker)) {
  2600. status = ERROR_OPERATION_ABORTED;
  2601. Resource->State = ClusterResourceOfflinePending;
  2602. goto error_exit;
  2603. }
  2604. retried = TRUE;
  2605. }
  2606. else {
  2607. //
  2608. // Delete the failed NTE.
  2609. //
  2610. IpaDeleteNte(
  2611. &(Resource->NteContext),
  2612. Resource->NodeParametersKey,
  2613. Resource->ResourceHandle
  2614. );
  2615. status = ERROR_CLUSTER_IPADDR_IN_USE;
  2616. ClusResLogSystemEventByKey1(
  2617. Resource->ResourceKey,
  2618. LOG_CRITICAL,
  2619. RES_IPADDR_IN_USE,
  2620. Resource->InternalPrivateProps.AddressString
  2621. );
  2622. (IpaLogEvent)(
  2623. Resource->ResourceHandle,
  2624. LOG_ERROR,
  2625. L"IP address %1!ws! is already in use on the network, status %2!u!.\n",
  2626. Resource->InternalPrivateProps.AddressString,
  2627. status
  2628. );
  2629. goto error_exit;
  2630. }
  2631. }
  2632. //
  2633. // Check to see if the online operation was aborted while this thread
  2634. // was blocked.
  2635. //
  2636. if (ClusWorkerCheckTerminate(pWorker)) {
  2637. status = ERROR_OPERATION_ABORTED;
  2638. Resource->State = ClusterResourceOfflinePending;
  2639. goto error_exit;
  2640. }
  2641. resourceStatus.CheckPoint++;
  2642. exit = (IpaSetResourceStatus)(Resource->ResourceHandle, &resourceStatus);
  2643. if ( exit == ResourceExitStateTerminate ) {
  2644. (IpaLogEvent)(
  2645. Resource->ResourceHandle,
  2646. LOG_ERROR,
  2647. L"Online thread aborted.\n"
  2648. );
  2649. status = ERROR_OPERATION_ABORTED;
  2650. goto error_exit;
  2651. }
  2652. if (Resource->EnableNetbios) {
  2653. //
  2654. // Bind NBT to the NTE
  2655. //
  2656. status = NbtBindInterface(
  2657. Resource->NbtDeviceName,
  2658. Resource->Address,
  2659. Resource->SubnetMask
  2660. );
  2661. if (status != ERROR_SUCCESS) {
  2662. (IpaLogEvent)(
  2663. Resource->ResourceHandle,
  2664. LOG_ERROR,
  2665. L"Failed to bind NBT interface %1!ws! to IP address %2!ws!, status %3!u!.\n",
  2666. Resource->NbtDeviceName,
  2667. Resource->InternalPrivateProps.AddressString,
  2668. status
  2669. );
  2670. //
  2671. // Delete the failed NBT interface.
  2672. //
  2673. IpaDeleteNbtInterface(
  2674. &(Resource->NbtDeviceName),
  2675. Resource->NodeParametersKey,
  2676. Resource->ResourceHandle
  2677. );
  2678. //
  2679. // Take the IP address offline
  2680. //
  2681. // In Windows 2000, TCP/IP ignores requests to set the address
  2682. // of an NTE if the underlying interface is disconnected.
  2683. // This can result in the same IP address being brought online
  2684. // on two different nodes. In order to workaround this bug
  2685. // in TCP/IP, we now delete the NTE during offline processing
  2686. // instead of reusing it.
  2687. //
  2688. // Note that IpaDeleteNte() invalidates the value
  2689. // of Resource->NteContext.
  2690. //
  2691. IpaDeleteNte(
  2692. &(Resource->NteContext),
  2693. Resource->NodeParametersKey,
  2694. Resource->ResourceHandle
  2695. );
  2696. #if 0
  2697. TcpipSetNTEAddress(Resource->NteContext, 0, 0);
  2698. #endif
  2699. goto error_exit;
  2700. }
  2701. //
  2702. // Set the WINS addresses
  2703. //
  2704. status = NbtSetWinsAddrInterface(
  2705. Resource->NbtDeviceName,
  2706. localParams->NbtPrimaryWinsAddress,
  2707. localParams->NbtSecondaryWinsAddress
  2708. );
  2709. if (status != ERROR_SUCCESS) {
  2710. ClusResLogSystemEventByKeyData1(
  2711. Resource->ResourceKey,
  2712. LOG_CRITICAL,
  2713. RES_IPADDR_WINS_ADDRESS_FAILED,
  2714. sizeof(status),
  2715. &status,
  2716. Resource->NbtDeviceName
  2717. );
  2718. (IpaLogEvent)(
  2719. Resource->ResourceHandle,
  2720. LOG_ERROR,
  2721. L"Failed to set WINS addresses on NBT interface %1!ws!, status %2!u!.\n",
  2722. Resource->NbtDeviceName,
  2723. status
  2724. );
  2725. //
  2726. // Delete the failed NBT interface.
  2727. //
  2728. IpaDeleteNbtInterface(
  2729. &(Resource->NbtDeviceName),
  2730. Resource->NodeParametersKey,
  2731. Resource->ResourceHandle
  2732. );
  2733. //
  2734. // Take the IP address offline
  2735. //
  2736. // In Windows 2000, TCP/IP ignores requests to set the address
  2737. // of an NTE if the underlying interface is disconnected.
  2738. // This can result in the same IP address being brought online
  2739. // on two different nodes. In order to workaround this bug
  2740. // in TCP/IP, we now delete the NTE during offline processing
  2741. // instead of reusing it.
  2742. //
  2743. // Note that IpaDeleteNte() invalidates the value
  2744. // of Resource->NteContext.
  2745. //
  2746. IpaDeleteNte(
  2747. &(Resource->NteContext),
  2748. Resource->NodeParametersKey,
  2749. Resource->ResourceHandle
  2750. );
  2751. #if 0
  2752. TcpipSetNTEAddress(Resource->NteContext, 0, 0);
  2753. #endif
  2754. goto error_exit;
  2755. }
  2756. }
  2757. //
  2758. // Tell the DNS resolver to update its list of local ip addresses.
  2759. //
  2760. // BUGBUG - The DNS resolver should do this automatically based
  2761. // on PnP events in the Whistler release. Remove this code
  2762. // after verifiying that functionality.
  2763. //
  2764. // This issue is tracked with bug 97134.
  2765. // DnsNotifyResolver(0, 0);
  2766. DnsNotifyResolverClusterIp((IP_ADDRESS)Resource->Address, TRUE);
  2767. Resource->State = ClusterResourceOnline;
  2768. resourceStatus.CheckPoint++;
  2769. resourceStatus.ResourceState = ClusterResourceOnline;
  2770. (IpaSetResourceStatus)(Resource->ResourceHandle, &resourceStatus);
  2771. (IpaLogEvent)(
  2772. Resource->ResourceHandle,
  2773. LOG_INFORMATION,
  2774. L"IP Address %1!ws! on adapter %2!ws! online\n",
  2775. Resource->InternalPrivateProps.AddressString,
  2776. localParams->AdapterName
  2777. );
  2778. IpaReleaseResourceLock(Resource);
  2779. IpaFreeLocalParameters(&newParams);
  2780. return(ERROR_SUCCESS);
  2781. error_exit:
  2782. ASSERT(status != ERROR_SUCCESS);
  2783. if (Resource->State == ClusterResourceOfflinePending) {
  2784. IpaDoOfflineProcessing(Resource, &resourceStatus);
  2785. //
  2786. // The resource lock was released.
  2787. //
  2788. }
  2789. else {
  2790. Resource->State = ClusterResourceFailed;
  2791. resourceStatus.CheckPoint++;
  2792. resourceStatus.ResourceState = ClusterResourceFailed;
  2793. (IpaSetResourceStatus)(Resource->ResourceHandle, &resourceStatus);
  2794. IpaReleaseResourceLock(Resource);
  2795. }
  2796. IpaFreeLocalParameters(&newParams);
  2797. return(status);
  2798. } // IpaOnlineThread
  2799. DWORD
  2800. WINAPI
  2801. IpaOnline(
  2802. IN RESID Resource,
  2803. IN OUT PHANDLE EventHandle
  2804. )
  2805. /*++
  2806. Routine Description:
  2807. Online routine for IP Address resource.
  2808. Arguments:
  2809. Resource - supplies resource id to be brought online
  2810. EventHandle - supplies a pointer to a handle to signal on error.
  2811. Return Value:
  2812. ERROR_SUCCESS if successful.
  2813. ERROR_RESOURCE_NOT_FOUND if RESID is not valid.
  2814. ERROR_RESOURCE_NOT_AVAILABLE if resource was arbitrated but failed to
  2815. acquire 'ownership'.
  2816. Win32 error code if other failure.
  2817. --*/
  2818. {
  2819. PIPA_RESOURCE resource = (PIPA_RESOURCE)Resource;
  2820. DWORD status;
  2821. if (resource != NULL) {
  2822. IpaAcquireResourceLock(resource);
  2823. (IpaLogEvent)(
  2824. resource->ResourceHandle,
  2825. LOG_INFORMATION,
  2826. L"Bringing resource online...\n",
  2827. Resource
  2828. );
  2829. ASSERT(resource->OnlineThread.hThread == NULL);
  2830. ASSERT(
  2831. (resource->State == ClusterResourceOffline) ||
  2832. (resource->State == ClusterResourceFailed)
  2833. );
  2834. resource->State = ClusterResourceOnlinePending;
  2835. status = ClusWorkerCreate(
  2836. &(resource->OnlineThread),
  2837. IpaOnlineThread,
  2838. resource
  2839. );
  2840. if (status != ERROR_SUCCESS) {
  2841. resource->State = ClusterResourceOffline;
  2842. (IpaLogEvent)(
  2843. resource->ResourceHandle,
  2844. LOG_ERROR,
  2845. L"Unable to start online thread, status %1!u!.\n",
  2846. status
  2847. );
  2848. } else {
  2849. status = ERROR_IO_PENDING;
  2850. }
  2851. IpaReleaseResourceLock(resource);
  2852. } else {
  2853. status = ERROR_RESOURCE_NOT_FOUND;
  2854. }
  2855. return(status);
  2856. } // IpaOnline
  2857. DWORD
  2858. IpaWorkerThread(
  2859. LPVOID Context
  2860. )
  2861. {
  2862. DWORD status;
  2863. DWORD dwFilter;
  2864. DWORD_PTR key;
  2865. DWORD event;
  2866. PIPA_RESOURCE resource;
  2867. CLUSTER_NETINTERFACE_STATE state;
  2868. HCHANGE notifyHandle;
  2869. IpaAcquireGlobalLock();
  2870. notifyHandle = IpaClusterNotifyHandle;
  2871. if (notifyHandle == NULL) {
  2872. if (!IsListEmpty(&IpaResourceList)) {
  2873. resource = CONTAINING_RECORD(
  2874. IpaResourceList.Flink,
  2875. IPA_RESOURCE,
  2876. Linkage
  2877. );
  2878. (IpaLogEvent)(
  2879. resource->ResourceHandle,
  2880. LOG_ERROR,
  2881. L"WorkerThread aborted.\n"
  2882. );
  2883. }
  2884. IpaReleaseGlobalLock();
  2885. return(ERROR_INVALID_PARAMETER);
  2886. }
  2887. if (!IsListEmpty(&IpaResourceList)) {
  2888. resource = CONTAINING_RECORD(
  2889. IpaResourceList.Flink,
  2890. IPA_RESOURCE,
  2891. Linkage
  2892. );
  2893. (IpaLogEvent)(
  2894. resource->ResourceHandle,
  2895. LOG_INFORMATION,
  2896. L"WorkerThread running\n"
  2897. );
  2898. }
  2899. IpaReleaseGlobalLock();
  2900. do {
  2901. status = GetClusterNotify(
  2902. notifyHandle,
  2903. &key,
  2904. &event,
  2905. NULL,
  2906. NULL,
  2907. INFINITE
  2908. );
  2909. if (status == ERROR_SUCCESS) {
  2910. if ( (event == CLUSTER_CHANGE_NETINTERFACE_STATE) ||
  2911. (event == CLUSTER_CHANGE_NETINTERFACE_DELETED)
  2912. )
  2913. {
  2914. IpaAcquireGlobalLock();
  2915. resource = IpaFindResourceInList((PVOID) key);
  2916. if (resource != NULL) {
  2917. IpaAcquireResourceLock(resource);
  2918. IpaReleaseGlobalLock();
  2919. if( (resource->State == ClusterResourceOnline) ||
  2920. (resource->State == ClusterResourceOnlinePending)
  2921. )
  2922. {
  2923. //
  2924. // Process the event.
  2925. //
  2926. if (event == CLUSTER_CHANGE_NETINTERFACE_STATE) {
  2927. resource->FailureStatus = ERROR_SUCCESS;
  2928. state = GetClusterNetInterfaceState(
  2929. resource->InterfaceHandle
  2930. );
  2931. if (state == ClusterNetInterfaceStateUnknown) {
  2932. status = GetLastError();
  2933. (IpaLogEvent)(
  2934. resource->ResourceHandle,
  2935. LOG_ERROR,
  2936. L"WorkerThread: Failed to get state for netinterface %1!ws!, status %2!u!.\n",
  2937. resource->LocalParams.InterfaceId,
  2938. status
  2939. );
  2940. }
  2941. else if ((state == ClusterNetInterfaceFailed) ||
  2942. (state == ClusterNetInterfaceUnavailable)
  2943. )
  2944. {
  2945. resource->FailureStatus = ERROR_IO_DEVICE;
  2946. (IpaLogEvent)(
  2947. resource->ResourceHandle,
  2948. LOG_WARNING,
  2949. L"WorkerThread: NetInterface %1!ws! has failed. Failing resource.\n",
  2950. resource->LocalParams.InterfaceId
  2951. );
  2952. }
  2953. else {
  2954. (IpaLogEvent)(
  2955. resource->ResourceHandle,
  2956. LOG_WARNING,
  2957. L"WorkerThread: NetInterface %1!ws! changed to state %2!u!.\n",
  2958. resource->LocalParams.InterfaceId,
  2959. state
  2960. );
  2961. }
  2962. }
  2963. else {
  2964. ASSERT(
  2965. event == CLUSTER_CHANGE_NETINTERFACE_DELETED
  2966. );
  2967. resource->FailureStatus = ERROR_DEV_NOT_EXIST;
  2968. (IpaLogEvent)(
  2969. resource->ResourceHandle,
  2970. LOG_ERROR,
  2971. L"WorkerThread: NetInterface %1!ws! was deleted. Failing resource.\n",
  2972. resource->LocalParams.InterfaceId
  2973. );
  2974. }
  2975. }
  2976. IpaReleaseResourceLock(resource);
  2977. }
  2978. else {
  2979. IpaReleaseGlobalLock();
  2980. }
  2981. }
  2982. else if (event == CLUSTER_CHANGE_HANDLE_CLOSE) {
  2983. //
  2984. // Time to exit.
  2985. //
  2986. break;
  2987. }
  2988. else {
  2989. IpaAcquireGlobalLock();
  2990. if (!IsListEmpty(&IpaResourceList)) {
  2991. resource = CONTAINING_RECORD(
  2992. IpaResourceList.Flink,
  2993. IPA_RESOURCE,
  2994. Linkage
  2995. );
  2996. (IpaLogEvent)(
  2997. resource->ResourceHandle,
  2998. LOG_WARNING,
  2999. L"WorkerThread: Received unknown event %1!u!.\n",
  3000. event
  3001. );
  3002. }
  3003. IpaReleaseGlobalLock();
  3004. ASSERT(event);
  3005. }
  3006. }
  3007. else {
  3008. IpaAcquireGlobalLock();
  3009. if (!IsListEmpty(&IpaResourceList)) {
  3010. resource = CONTAINING_RECORD(
  3011. IpaResourceList.Flink,
  3012. IPA_RESOURCE,
  3013. Linkage
  3014. );
  3015. (IpaLogEvent)(
  3016. resource->ResourceHandle,
  3017. LOG_ERROR,
  3018. L"WorkerThread: GetClusterNotify failed with status %1!u!.\n",
  3019. status
  3020. );
  3021. }
  3022. IpaReleaseGlobalLock();
  3023. break;
  3024. }
  3025. } while (status == ERROR_SUCCESS);
  3026. IpaAcquireGlobalLock();
  3027. if (!IsListEmpty(&IpaResourceList)) {
  3028. resource = CONTAINING_RECORD(
  3029. IpaResourceList.Flink,
  3030. IPA_RESOURCE,
  3031. Linkage
  3032. );
  3033. (IpaLogEvent)(
  3034. resource->ResourceHandle,
  3035. LOG_INFORMATION,
  3036. L"WorkerThread terminating\n"
  3037. );
  3038. }
  3039. IpaReleaseGlobalLock();
  3040. return(status);
  3041. } // IpaWorkerThread
  3042. BOOL
  3043. WINAPI
  3044. IpaInternalLooksAlive(
  3045. IN RESID Resource,
  3046. IN LPWSTR Mode
  3047. )
  3048. /*++
  3049. Routine Description:
  3050. LooksAlive routine for IP Address resource.
  3051. Arguments:
  3052. Resource - supplies the resource id to be polled.
  3053. Mode - string indicating "Looks" or "Is"
  3054. Return Value:
  3055. TRUE - Resource looks like it is alive and well
  3056. FALSE - Resource looks like it is toast.
  3057. --*/
  3058. {
  3059. PIPA_RESOURCE resource = (PIPA_RESOURCE) Resource;
  3060. BOOLEAN returnValue = TRUE;
  3061. TCPIP_NTE_INFO nteInfo;
  3062. DWORD status;
  3063. IPAddr address;
  3064. DWORD instance;
  3065. if (resource != NULL) {
  3066. IpaAcquireResourceLock(resource);
  3067. if (resource->FailureStatus == ERROR_SUCCESS) {
  3068. status = TcpipGetNTEInfo(resource->NteContext, &nteInfo);
  3069. if (status != ERROR_SUCCESS) {
  3070. returnValue = FALSE;
  3071. }
  3072. else if (nteInfo.Instance == resource->NteInstance) {
  3073. if (resource->EnableNetbios) {
  3074. status = NbtGetInterfaceInfo(
  3075. resource->NbtDeviceName,
  3076. &address,
  3077. &instance
  3078. );
  3079. if (status != ERROR_SUCCESS) {
  3080. returnValue = FALSE;
  3081. }
  3082. else if (instance != resource->NbtDeviceInstance) {
  3083. status = ERROR_DEV_NOT_EXIST;
  3084. returnValue = FALSE;
  3085. }
  3086. }
  3087. }
  3088. else {
  3089. status = ERROR_DEV_NOT_EXIST;
  3090. returnValue = FALSE;
  3091. }
  3092. }
  3093. else {
  3094. status = resource->FailureStatus;
  3095. returnValue = FALSE;
  3096. }
  3097. if (!returnValue) {
  3098. ClusResLogSystemEventByKeyData(
  3099. resource->ResourceKey,
  3100. LOG_CRITICAL,
  3101. RES_IPADDR_NTE_INTERFACE_FAILED,
  3102. sizeof(status),
  3103. &status
  3104. );
  3105. (IpaLogEvent)(
  3106. resource->ResourceHandle,
  3107. LOG_WARNING,
  3108. L"IP Interface %1!u! (address %2!ws!) failed %3!ws!Alive check, status %4!u!, address 0x%5!lx!, instance 0x%6!lx!.\n",
  3109. resource->NteContext,
  3110. resource->InternalPrivateProps.AddressString,
  3111. Mode,
  3112. status,
  3113. address,
  3114. resource->NteInstance
  3115. );
  3116. }
  3117. IpaReleaseResourceLock(resource);
  3118. }
  3119. return(returnValue);
  3120. } // IpaInternalLooksAliveCheck
  3121. BOOL
  3122. WINAPI
  3123. IpaLooksAlive(
  3124. IN RESID Resource
  3125. )
  3126. /*++
  3127. Routine Description:
  3128. LooksAlive routine for IP Address resource.
  3129. Arguments:
  3130. Resource - supplies the resource id to be polled.
  3131. Return Value:
  3132. TRUE - Resource looks like it is alive and well
  3133. FALSE - Resource looks like it is toast.
  3134. --*/
  3135. {
  3136. return(IpaInternalLooksAlive(Resource, L"Looks"));
  3137. }
  3138. BOOL
  3139. WINAPI
  3140. IpaIsAlive(
  3141. IN RESID Resource
  3142. )
  3143. /*++
  3144. Routine Description:
  3145. IsAlive routine for IP Address resource.
  3146. Arguments:
  3147. Resource - supplies the resource id to be polled.
  3148. Return Value:
  3149. TRUE - Resource is alive and well
  3150. FALSE - Resource is toast.
  3151. --*/
  3152. {
  3153. return(IpaInternalLooksAlive(Resource, L"Is"));
  3154. }
  3155. VOID
  3156. WINAPI
  3157. IpaClose(
  3158. IN RESID Resource
  3159. )
  3160. /*++
  3161. Routine Description:
  3162. Close routine for IP Address resource.
  3163. Arguments:
  3164. Resource - supplies resource id to be closed.
  3165. Return Value:
  3166. None.
  3167. --*/
  3168. {
  3169. PIPA_RESOURCE resource = (PIPA_RESOURCE)Resource;
  3170. PLIST_ENTRY entry;
  3171. TCPIP_NTE_INFO nteInfo;
  3172. DWORD status;
  3173. if (resource != NULL) {
  3174. //
  3175. // First, terminate the online thread without the lock.
  3176. //
  3177. ClusWorkerTerminate(&(resource->OnlineThread));
  3178. IpaAcquireGlobalLock();
  3179. IpaAcquireResourceLock(resource);
  3180. //
  3181. // Remove the resource from the global list
  3182. //
  3183. RemoveEntryList(&(resource->Linkage));
  3184. IpaReleaseResourceLock(resource);
  3185. IpaOpenResourceCount--;
  3186. if ((IpaOpenResourceCount == 0) && (IpaClusterHandle != NULL)) {
  3187. HCLUSTER handle = IpaClusterHandle;
  3188. IpaClusterHandle = NULL;
  3189. IpaReleaseGlobalLock();
  3190. CloseCluster(handle);
  3191. }
  3192. else {
  3193. IpaReleaseGlobalLock();
  3194. }
  3195. //
  3196. // Delete the resource's parameters
  3197. //
  3198. if (resource->NbtDeviceName != NULL) {
  3199. //
  3200. // Try to delete it.
  3201. //
  3202. IpaDeleteNbtInterface(
  3203. &(resource->NbtDeviceName),
  3204. resource->NodeParametersKey,
  3205. resource->ResourceHandle
  3206. );
  3207. }
  3208. if (resource->NteContext != INVALID_NTE_CONTEXT) {
  3209. //
  3210. // Try to delete it.
  3211. //
  3212. IpaDeleteNte(
  3213. &(resource->NteContext),
  3214. resource->NodeParametersKey,
  3215. resource->ResourceHandle
  3216. );
  3217. }
  3218. IpaFreePrivateProperties(&(resource->InternalPrivateProps));
  3219. IpaFreeLocalParameters(&(resource->LocalParams));
  3220. if (resource->ResourceKey != NULL) {
  3221. ClusterRegCloseKey(resource->ResourceKey);
  3222. }
  3223. if (resource->ParametersKey != NULL) {
  3224. ClusterRegCloseKey(resource->ParametersKey);
  3225. }
  3226. if (resource->NodeParametersKey != NULL) {
  3227. ClusterRegCloseKey(resource->NodeParametersKey);
  3228. }
  3229. if (resource->NetworksKey != NULL) {
  3230. ClusterRegCloseKey(resource->NetworksKey);
  3231. }
  3232. if (resource->InterfacesKey != NULL) {
  3233. ClusterRegCloseKey(resource->InterfacesKey);
  3234. }
  3235. DeleteCriticalSection(&(resource->Lock));
  3236. (IpaLogEvent)(
  3237. resource->ResourceHandle,
  3238. LOG_INFORMATION,
  3239. L"Resource closed.\n"
  3240. );
  3241. LocalFree(resource);
  3242. }
  3243. return;
  3244. } // IpaClose
  3245. DWORD
  3246. IpaResourceControl(
  3247. IN RESID ResourceId,
  3248. IN DWORD ControlCode,
  3249. IN PVOID InBuffer,
  3250. IN DWORD InBufferSize,
  3251. OUT PVOID OutBuffer,
  3252. IN DWORD OutBufferSize,
  3253. OUT LPDWORD BytesReturned
  3254. )
  3255. /*++
  3256. Routine Description:
  3257. ResourceControl routine for Generic Application resources.
  3258. Perform the control request specified by ControlCode on the specified
  3259. resource.
  3260. Arguments:
  3261. ResourceId - Supplies the resource id for the specific resource.
  3262. ControlCode - Supplies the control code that defines the action
  3263. to be performed.
  3264. InBuffer - Supplies a pointer to a buffer containing input data.
  3265. InBufferSize - Supplies the size, in bytes, of the data pointed
  3266. to by InBuffer.
  3267. OutBuffer - Supplies a pointer to the output buffer to be filled in.
  3268. OutBufferSize - Supplies the size, in bytes, of the available space
  3269. pointed to by OutBuffer.
  3270. BytesReturned - Returns the number of bytes of OutBuffer actually
  3271. filled in by the resource. If OutBuffer is too small, BytesReturned
  3272. contains the total number of bytes for the operation to succeed.
  3273. Return Value:
  3274. ERROR_SUCCESS - The function completed successfully.
  3275. ERROR_INVALID_FUNCTION - The requested control code is not supported.
  3276. In some cases, this allows the cluster software to perform the work.
  3277. Win32 error code - The function failed.
  3278. Notes:
  3279. We don't need to acquire the resource lock because the Cluster Service
  3280. guarantees synchronization with other APIs.
  3281. --*/
  3282. {
  3283. DWORD status;
  3284. PIPA_RESOURCE resource = (PIPA_RESOURCE) ResourceId;
  3285. DWORD resourceIndex;
  3286. DWORD required;
  3287. if ( resource == NULL ) {
  3288. DBG_PRINT( "IPAddress: ResourceControl request for a nonexistent resource id 0x%p\n",
  3289. ResourceId );
  3290. return(FALSE);
  3291. }
  3292. switch ( ControlCode ) {
  3293. case CLUSCTL_RESOURCE_UNKNOWN:
  3294. *BytesReturned = 0;
  3295. status = ERROR_SUCCESS;
  3296. break;
  3297. case CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTY_FMTS:
  3298. status = ResUtilGetPropertyFormats( IpaResourcePrivateProperties,
  3299. OutBuffer,
  3300. OutBufferSize,
  3301. BytesReturned,
  3302. &required );
  3303. if ( status == ERROR_MORE_DATA ) {
  3304. *BytesReturned = required;
  3305. }
  3306. break;
  3307. case CLUSCTL_RESOURCE_ENUM_PRIVATE_PROPERTIES:
  3308. status = ResUtilEnumProperties(
  3309. IpaResourcePrivateProperties,
  3310. OutBuffer,
  3311. OutBufferSize,
  3312. BytesReturned,
  3313. &required
  3314. );
  3315. if ( status == ERROR_MORE_DATA ) {
  3316. *BytesReturned = required;
  3317. }
  3318. break;
  3319. case CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES:
  3320. status = IpaGetPrivateResProperties(
  3321. resource,
  3322. OutBuffer,
  3323. OutBufferSize,
  3324. BytesReturned
  3325. );
  3326. break;
  3327. case CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES:
  3328. status = IpaValidatePrivateResProperties(
  3329. resource,
  3330. InBuffer,
  3331. InBufferSize,
  3332. NULL
  3333. );
  3334. break;
  3335. case CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES:
  3336. status = IpaSetPrivateResProperties(
  3337. resource,
  3338. InBuffer,
  3339. InBufferSize
  3340. );
  3341. break;
  3342. default:
  3343. status = ERROR_INVALID_FUNCTION;
  3344. break;
  3345. }
  3346. return(status);
  3347. } // IpaResourceControl
  3348. DWORD
  3349. IpaResourceTypeControl(
  3350. IN LPCWSTR ResourceTypeName,
  3351. IN DWORD ControlCode,
  3352. IN PVOID InBuffer,
  3353. IN DWORD InBufferSize,
  3354. OUT PVOID OutBuffer,
  3355. IN DWORD OutBufferSize,
  3356. OUT LPDWORD BytesReturned
  3357. )
  3358. /*++
  3359. Routine Description:
  3360. ResourceTypeControl routine for Generic Application resources.
  3361. Perform the control request specified by ControlCode on this resource type.
  3362. Arguments:
  3363. ResourceTypeName - Supplies the resource type name.
  3364. ControlCode - Supplies the control code that defines the action
  3365. to be performed.
  3366. InBuffer - Supplies a pointer to a buffer containing input data.
  3367. InBufferSize - Supplies the size, in bytes, of the data pointed
  3368. to by InBuffer.
  3369. OutBuffer - Supplies a pointer to the output buffer to be filled in.
  3370. OutBufferSize - Supplies the size, in bytes, of the available space
  3371. pointed to by OutBuffer.
  3372. BytesReturned - Returns the number of bytes of OutBuffer actually
  3373. filled in by the resource. If OutBuffer is too small, BytesReturned
  3374. contains the total number of bytes for the operation to succeed.
  3375. Return Value:
  3376. ERROR_SUCCESS - The function completed successfully.
  3377. ERROR_INVALID_FUNCTION - The requested control code is not supported.
  3378. In some cases, this allows the cluster software to perform the work.
  3379. Win32 error code - The function failed.
  3380. Notes:
  3381. We don't need to acquire the resource lock because the Cluster Service
  3382. guarantees synchronization with other APIs.
  3383. --*/
  3384. {
  3385. DWORD status;
  3386. DWORD required;
  3387. switch ( ControlCode ) {
  3388. case CLUSCTL_RESOURCE_TYPE_UNKNOWN:
  3389. *BytesReturned = 0;
  3390. status = ERROR_SUCCESS;
  3391. break;
  3392. case CLUSCTL_RESOURCE_TYPE_GET_PRIVATE_RESOURCE_PROPERTY_FMTS:
  3393. status = ResUtilGetPropertyFormats( IpaResourcePrivateProperties,
  3394. OutBuffer,
  3395. OutBufferSize,
  3396. BytesReturned,
  3397. &required );
  3398. if ( status == ERROR_MORE_DATA ) {
  3399. *BytesReturned = required;
  3400. }
  3401. break;
  3402. case CLUSCTL_RESOURCE_TYPE_ENUM_PRIVATE_PROPERTIES:
  3403. status = ResUtilEnumProperties(
  3404. IpaResourcePrivateProperties,
  3405. OutBuffer,
  3406. OutBufferSize,
  3407. BytesReturned,
  3408. &required
  3409. );
  3410. if ( status == ERROR_MORE_DATA ) {
  3411. *BytesReturned = required;
  3412. }
  3413. break;
  3414. default:
  3415. status = ERROR_INVALID_FUNCTION;
  3416. break;
  3417. }
  3418. return(status);
  3419. } // IpaResourceTypeControl
  3420. DWORD
  3421. IpaGetPrivateResProperties(
  3422. IN OUT PIPA_RESOURCE Resource,
  3423. OUT PVOID OutBuffer,
  3424. IN DWORD OutBufferSize,
  3425. OUT LPDWORD BytesReturned
  3426. )
  3427. /*++
  3428. Routine Description:
  3429. Processes the CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES control function
  3430. for resources of type IP Address.
  3431. Arguments:
  3432. Resource - Supplies the resource entry on which to operate.
  3433. OutBuffer - Returns the output data.
  3434. OutBufferSize - Supplies the size, in bytes, of the data pointed
  3435. to by OutBuffer.
  3436. BytesReturned - The number of bytes returned in OutBuffer.
  3437. Return Value:
  3438. ERROR_SUCCESS - The function completed successfully.
  3439. ERROR_INVALID_PARAMETER - The data is formatted incorrectly.
  3440. ERROR_NOT_ENOUGH_MEMORY - An error occurred allocating memory.
  3441. Win32 error code - The function failed.
  3442. Notes:
  3443. We don't need to acquire the resource lock because the Cluster Service
  3444. guarantees synchronization with other APIs.
  3445. --*/
  3446. {
  3447. DWORD status;
  3448. DWORD statusReturn = ERROR_SUCCESS;
  3449. DWORD required;
  3450. IPA_PRIVATE_PROPS props;
  3451. LPWSTR networkName;
  3452. LPWSTR nameOfPropInError;
  3453. ZeroMemory(&props, sizeof(props));
  3454. status = ResUtilGetPropertiesToParameterBlock(
  3455. Resource->ParametersKey,
  3456. IpaResourcePrivateProperties,
  3457. (LPBYTE) &props,
  3458. FALSE, /*CheckForRequiredProperties*/
  3459. &nameOfPropInError
  3460. );
  3461. if ( status != ERROR_SUCCESS ) {
  3462. (IpaLogEvent)(
  3463. Resource->ResourceHandle,
  3464. LOG_ERROR,
  3465. L"Unable to read the '%1' property. Error: %2!u!.\n",
  3466. (nameOfPropInError == NULL ? L"" : nameOfPropInError),
  3467. status );
  3468. statusReturn = status;
  3469. goto error_exit;
  3470. }
  3471. //
  3472. // Find the name of the network if we read the network GUID.
  3473. //
  3474. if ( props.NetworkString != NULL ) {
  3475. networkName = IpaGetNameOfNetworkPatchGuidIfNecessary(Resource, &props);
  3476. if ( networkName == NULL ) {
  3477. status = GetLastError();
  3478. (IpaLogEvent)(
  3479. Resource->ResourceHandle,
  3480. LOG_WARNING,
  3481. L"Error getting name of network whose GUID is '%1' property. Error: %2!u!.\n",
  3482. props.NetworkString,
  3483. status
  3484. );
  3485. status = ERROR_SUCCESS;
  3486. } else {
  3487. LocalFree( props.NetworkString );
  3488. props.NetworkString = networkName;
  3489. }
  3490. }
  3491. //
  3492. // Construct a property list from the parameter block.
  3493. //
  3494. status = ResUtilPropertyListFromParameterBlock(
  3495. IpaResourcePrivateProperties,
  3496. OutBuffer,
  3497. &OutBufferSize,
  3498. (LPBYTE) &props,
  3499. BytesReturned,
  3500. &required
  3501. );
  3502. //
  3503. // Add unknown properties to the property list.
  3504. //
  3505. if ( (status == ERROR_SUCCESS) || (status == ERROR_MORE_DATA ) ) {
  3506. statusReturn = status;
  3507. status = ResUtilAddUnknownProperties(
  3508. Resource->ParametersKey,
  3509. IpaResourcePrivateProperties,
  3510. OutBuffer,
  3511. OutBufferSize,
  3512. BytesReturned,
  3513. &required
  3514. );
  3515. if ( status != ERROR_SUCCESS ) {
  3516. statusReturn = status;
  3517. }
  3518. if ( statusReturn == ERROR_MORE_DATA ) {
  3519. *BytesReturned = required;
  3520. }
  3521. }
  3522. error_exit:
  3523. ResUtilFreeParameterBlock(
  3524. (LPBYTE) &props,
  3525. NULL,
  3526. IpaResourcePrivateProperties
  3527. );
  3528. return(statusReturn);
  3529. } // IpaGetPrivateResProperties
  3530. DWORD
  3531. IpaValidatePrivateResProperties(
  3532. IN OUT PIPA_RESOURCE Resource,
  3533. IN PVOID InBuffer,
  3534. IN DWORD InBufferSize,
  3535. OUT PIPA_PRIVATE_PROPS Props
  3536. )
  3537. /*++
  3538. Routine Description:
  3539. Processes the CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES control
  3540. function for resources of type IP Address.
  3541. Arguments:
  3542. Resource - Supplies the resource entry on which to operate.
  3543. InBuffer - Supplies a pointer to a buffer containing input data.
  3544. InBufferSize - Supplies the size, in bytes, of the data pointed
  3545. to by InBuffer.
  3546. Props - Supplies the property block to fill in.
  3547. Return Value:
  3548. ERROR_SUCCESS - The function completed successfully.
  3549. ERROR_INVALID_PARAMETER - The data is formatted incorrectly.
  3550. ERROR_NOT_ENOUGH_MEMORY - An error occurred allocating memory.
  3551. Win32 error code - The function failed.
  3552. Notes:
  3553. We don't need to acquire the resource lock because the Cluster Service
  3554. guarantees synchronization with other APIs.
  3555. --*/
  3556. {
  3557. DWORD status;
  3558. DWORD required;
  3559. IPA_PRIVATE_PROPS currentProps;
  3560. LPWSTR networkId;
  3561. LPWSTR networkName;
  3562. LPWSTR nameOfPropInError;
  3563. IPA_PRIVATE_PROPS newProps;
  3564. PIPA_PRIVATE_PROPS pNewProps = NULL;
  3565. //
  3566. // Check if there is input data.
  3567. //
  3568. if ( (InBuffer == NULL) || (InBufferSize < sizeof(DWORD)) ) {
  3569. return(ERROR_INVALID_DATA);
  3570. }
  3571. //
  3572. // Capture the current set of private properties from the registry.
  3573. //
  3574. ZeroMemory(&currentProps, sizeof(currentProps));
  3575. IpaAcquireResourceLock(Resource);
  3576. status = ResUtilGetPropertiesToParameterBlock(
  3577. Resource->ParametersKey,
  3578. IpaResourcePrivateProperties,
  3579. (LPBYTE) &currentProps,
  3580. FALSE, /*CheckForRequiredProperties*/
  3581. &nameOfPropInError
  3582. );
  3583. IpaReleaseResourceLock(Resource);
  3584. if ( status != ERROR_SUCCESS ) {
  3585. (IpaLogEvent)(
  3586. Resource->ResourceHandle,
  3587. LOG_ERROR,
  3588. L"Unable to read the '%1' property. Error: %2!u!.\n",
  3589. (nameOfPropInError == NULL ? L"" : nameOfPropInError),
  3590. status );
  3591. goto error_exit;
  3592. }
  3593. //
  3594. // Find the name of the network if we read the network GUID.
  3595. //
  3596. if ( currentProps.NetworkString != NULL ) {
  3597. networkName = IpaGetNameOfNetworkPatchGuidIfNecessary(
  3598. Resource,
  3599. &currentProps
  3600. );
  3601. if ( networkName == NULL ) {
  3602. //
  3603. // this is not necessarily an error. Changing the network of the
  3604. // NIC on which this resource is dependent will cause the old
  3605. // network GUID in the registry to be invalid. If the user has
  3606. // specified a new network, we'll discover later on in this
  3607. // routine and get the correct GUID.
  3608. //
  3609. status = GetLastError();
  3610. (IpaLogEvent)(
  3611. Resource->ResourceHandle,
  3612. LOG_WARNING,
  3613. L"Error getting name of network whose GUID is '%1' property. Error: %2!u!.\n",
  3614. currentProps.NetworkString,
  3615. status
  3616. );
  3617. }
  3618. LocalFree( currentProps.NetworkString );
  3619. currentProps.NetworkString = networkName;
  3620. }
  3621. //
  3622. // Duplicate the current parameter block.
  3623. //
  3624. if ( Props == NULL ) {
  3625. pNewProps = &newProps;
  3626. } else {
  3627. pNewProps = Props;
  3628. }
  3629. ZeroMemory( pNewProps, sizeof(IPA_PRIVATE_PROPS) );
  3630. status = ResUtilDupParameterBlock(
  3631. (LPBYTE) pNewProps,
  3632. (LPBYTE) &currentProps,
  3633. IpaResourcePrivateProperties
  3634. );
  3635. if ( status != ERROR_SUCCESS ) {
  3636. goto error_exit;
  3637. }
  3638. //
  3639. // Parse and validate the new properties.
  3640. //
  3641. status = ResUtilVerifyPropertyTable(
  3642. IpaResourcePrivateProperties,
  3643. NULL,
  3644. TRUE, // Allow unknowns
  3645. InBuffer,
  3646. InBufferSize,
  3647. (LPBYTE) pNewProps
  3648. );
  3649. if ( status == ERROR_SUCCESS ) {
  3650. ULONG newIpAddress = 0;
  3651. //
  3652. // Validate the parameter values.
  3653. //
  3654. if (pNewProps->NetworkString != NULL) {
  3655. //
  3656. // Get the network ID for the specified network.
  3657. //
  3658. networkId = IpaGetIdOfNetwork(
  3659. Resource,
  3660. pNewProps->NetworkString
  3661. );
  3662. if ( networkId == NULL ) {
  3663. status = GetLastError();
  3664. goto error_exit;
  3665. }
  3666. LocalFree( pNewProps->NetworkString );
  3667. pNewProps->NetworkString = networkId;
  3668. }
  3669. if (pNewProps->AddressString != NULL) {
  3670. //
  3671. // Validate the IP address.
  3672. //
  3673. ULONG nAddress;
  3674. status = ClRtlTcpipStringToAddress(
  3675. pNewProps->AddressString,
  3676. &nAddress
  3677. );
  3678. if ( status != ERROR_SUCCESS ) {
  3679. goto error_exit;
  3680. }
  3681. if ( ClRtlIsValidTcpipAddress( nAddress ) == FALSE ) {
  3682. status = ERROR_INVALID_PARAMETER;
  3683. goto error_exit;
  3684. }
  3685. newIpAddress = nAddress;
  3686. //
  3687. // if the address is changed, make sure it is not a duplicate
  3688. //
  3689. if (lstrcmpW(
  3690. pNewProps->AddressString,
  3691. currentProps.AddressString
  3692. ) != 0
  3693. )
  3694. {
  3695. BOOL isDuplicate;
  3696. isDuplicate = ClRtlIsDuplicateTcpipAddress(nAddress);
  3697. if (isDuplicate) {
  3698. //
  3699. // If this isn't the address we currently have online,
  3700. // then it is a duplicate.
  3701. //
  3702. IpaAcquireResourceLock(Resource);
  3703. if (!( ((Resource->State == ClusterResourceOnlinePending)
  3704. ||
  3705. (Resource->State == ClusterResourceOnline)
  3706. ||
  3707. (Resource->State == ClusterResourceOfflinePending)
  3708. )
  3709. &&
  3710. (lstrcmpW(
  3711. pNewProps->AddressString,
  3712. Resource->InternalPrivateProps.AddressString
  3713. ) == 0
  3714. )
  3715. )
  3716. )
  3717. {
  3718. status = ERROR_CLUSTER_IPADDR_IN_USE;
  3719. IpaReleaseResourceLock(Resource);
  3720. goto error_exit;
  3721. }
  3722. IpaReleaseResourceLock(Resource);
  3723. }
  3724. }
  3725. }
  3726. if (pNewProps->SubnetMaskString != NULL) {
  3727. //
  3728. // Validate the subnet mask.
  3729. //
  3730. ULONG nAddress;
  3731. status = ClRtlTcpipStringToAddress(
  3732. pNewProps->SubnetMaskString,
  3733. &nAddress
  3734. );
  3735. if ( status != ERROR_SUCCESS ) {
  3736. goto error_exit;
  3737. }
  3738. if ( ClRtlIsValidTcpipSubnetMask( nAddress ) == FALSE ) {
  3739. status = ERROR_INVALID_PARAMETER;
  3740. goto error_exit;
  3741. }
  3742. if (newIpAddress &&
  3743. (ClRtlIsValidTcpipAddressAndSubnetMask(newIpAddress, nAddress) == FALSE) ) {
  3744. status = ERROR_INVALID_PARAMETER;
  3745. goto error_exit;
  3746. }
  3747. }
  3748. }
  3749. error_exit:
  3750. //
  3751. // Cleanup our parameter block.
  3752. //
  3753. if (
  3754. ( status != ERROR_SUCCESS && pNewProps != NULL )
  3755. ||
  3756. ( pNewProps == &newProps )
  3757. )
  3758. {
  3759. ResUtilFreeParameterBlock(
  3760. (LPBYTE) pNewProps,
  3761. (LPBYTE) &currentProps,
  3762. IpaResourcePrivateProperties
  3763. );
  3764. }
  3765. ResUtilFreeParameterBlock(
  3766. (LPBYTE) &currentProps,
  3767. NULL,
  3768. IpaResourcePrivateProperties
  3769. );
  3770. return(status);
  3771. } // IpaValidatePrivateResProperties
  3772. DWORD
  3773. IpaSetPrivateResProperties(
  3774. IN OUT PIPA_RESOURCE Resource,
  3775. IN PVOID InBuffer,
  3776. IN DWORD InBufferSize
  3777. )
  3778. /*++
  3779. Routine Description:
  3780. Processes the CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES control function
  3781. for resources of type IP Address.
  3782. Arguments:
  3783. Resource - Supplies the resource entry on which to operate.
  3784. InBuffer - Supplies a pointer to a buffer containing input data.
  3785. InBufferSize - Supplies the size, in bytes, of the data pointed
  3786. to by InBuffer.
  3787. Return Value:
  3788. ERROR_SUCCESS - The function completed successfully.
  3789. ERROR_INVALID_PARAMETER - The data is formatted incorrectly.
  3790. ERROR_NOT_ENOUGH_MEMORY - An error occurred allocating memory.
  3791. Win32 error code - The function failed.
  3792. Notes:
  3793. We don't need to acquire the resource lock because the Cluster Service
  3794. guarantees synchronization with other APIs. The asynchronous OnlineThread
  3795. isn't a problem because we captured its properties during the IpaOnline
  3796. routine.
  3797. --*/
  3798. {
  3799. DWORD status;
  3800. IPA_PRIVATE_PROPS props;
  3801. ZeroMemory( &props, sizeof(IPA_PRIVATE_PROPS) );
  3802. //
  3803. // Parse the properties so they can be validated together.
  3804. // This routine does individual property validation.
  3805. //
  3806. status = IpaValidatePrivateResProperties(
  3807. Resource,
  3808. InBuffer,
  3809. InBufferSize,
  3810. &props
  3811. );
  3812. if ( status != ERROR_SUCCESS ) {
  3813. return(status);
  3814. }
  3815. IpaAcquireResourceLock(Resource);
  3816. //
  3817. // Save the parameter values.
  3818. //
  3819. status = ResUtilSetPropertyParameterBlock(
  3820. Resource->ParametersKey,
  3821. IpaResourcePrivateProperties,
  3822. NULL,
  3823. (LPBYTE) &props,
  3824. InBuffer,
  3825. InBufferSize,
  3826. NULL
  3827. );
  3828. //
  3829. // If the resource is online, return a non-success status.
  3830. //
  3831. // Note that we count on the fact that 32-bit reads are atomic.
  3832. //
  3833. if (status == ERROR_SUCCESS) {
  3834. DWORD state = Resource->State;
  3835. if ( (state == ClusterResourceOnline) ||
  3836. (state == ClusterResourceOnlinePending)
  3837. )
  3838. {
  3839. status = ERROR_RESOURCE_PROPERTIES_STORED;
  3840. } else {
  3841. status = ERROR_SUCCESS;
  3842. }
  3843. }
  3844. IpaReleaseResourceLock(Resource);
  3845. ResUtilFreeParameterBlock(
  3846. (LPBYTE) &props,
  3847. NULL,
  3848. IpaResourcePrivateProperties
  3849. );
  3850. return status;
  3851. } // IpaSetPrivateResProperties
  3852. //***********************************************************
  3853. //
  3854. // Define Function Table
  3855. //
  3856. //***********************************************************
  3857. CLRES_V1_FUNCTION_TABLE( IpAddrFunctionTable, // Name
  3858. CLRES_VERSION_V1_00, // Version
  3859. Ipa, // Prefix
  3860. NULL, // Arbitrate
  3861. NULL, // Release
  3862. IpaResourceControl, // ResControl
  3863. IpaResourceTypeControl ); // ResTypeControl