Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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