windows-nt/Source/XPSP1/NT/base/cluster/clnetcfg/clnetcfg.c

2373 lines
63 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
clnetcfg.c
Abstract:
System network configuration grovelling routines
Author:
Mike Massa (mikemas) May 19, 1997
Revision History:
Who When What
-------- -------- ----------------------------------------------
mikemas 05-19-97 created
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <cluster.h>
#include <clusrpc.h>
#include <clnetcfg.h>
#include <wchar.h>
//
// Private constants
//
#define CLNET_DEFAULT_NETWORK_PRIORITY 0xffffffff
//
// Private Data
//
LPFN_CLNETPRINT pClNetPrint = NULL;
LPFN_CLNETLOGEVENT pClNetLogEvent = NULL;
LPFN_CLNETLOGEVENT1 pClNetLogEvent1 = NULL;
LPFN_CLNETLOGEVENT2 pClNetLogEvent2 = NULL;
LPFN_CLNETLOGEVENT3 pClNetLogEvent3 = NULL;
WCHAR ClNetpEmptyString[] = L"";
//
// Private Macros
//
#if DBG
#define ClNetDbgPrint(arg) (*pClNetPrint) arg
#else
#define ClNetDbgPrint(arg)
#endif
//
// Private utility routines
//
VOID
ClNetpConsumeAdaptersOnNetwork(
IN PCLRTL_NET_ADAPTER_ENUM AdapterEnum,
IN LPWSTR NetworkAddress
)
{
PCLRTL_NET_ADAPTER_INFO adapterInfo;
PCLRTL_NET_INTERFACE_INFO adapterIfInfo;
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Consuming all adapters on IP network %1!ws!.\n",
NetworkAddress
));
//
// Walk the adapter enum and consume all other adapters
// attached to this network.
//
for (adapterInfo = AdapterEnum->AdapterList;
adapterInfo != NULL;
adapterInfo = adapterInfo->Next
)
{
if (adapterInfo->Ignore == FALSE) {
adapterIfInfo = ClRtlFindNetInterfaceByNetworkAddress(
adapterInfo,
NetworkAddress
);
if (adapterIfInfo != NULL) {
//
// This is a duplicate adapter.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Consumed adapter '%1!ws!'.\n",
adapterInfo->DeviceName
));
adapterInfo->Ignore = TRUE;
}
}
}
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Finished consuming all adapters on IP network %1!ws!.\n",
NetworkAddress
));
return;
} // ClNetpConsumeAdaptersOnNetwork
LPWSTR
ClNetpCloneString(
LPWSTR String
)
{
LPWSTR newString = LocalAlloc(
LMEM_FIXED,
(lstrlenW(String) + 1) * sizeof(UNICODE_NULL)
);
if (newString != NULL) {
lstrcpyW(newString, String);
}
return(newString);
} // ClNetpCloneString
BOOLEAN
ClNetpIsNetworkNameUnique(
IN LPWSTR NetworkName,
IN PCLNET_CONFIG_LISTS ConfigLists,
IN PLIST_ENTRY UnchangedConfigList
)
{
PLIST_ENTRY listEntry;
PCLNET_CONFIG_ENTRY configEntry;
PLIST_ENTRY listHead;
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Checking uniqueness of net name '%1!ws!'\n",
NetworkName
));
//
// Check the existing cluster network definitions for a duplicate
//
listHead = &(ConfigLists->InputConfigList);
for (;;) {
for (listEntry = listHead->Flink;
listEntry != listHead;
listEntry = listEntry->Flink
)
{
configEntry = CONTAINING_RECORD(
listEntry,
CLNET_CONFIG_ENTRY,
Linkage
);
if (lstrcmpiW(NetworkName, configEntry->NetworkInfo.Name) == 0) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Net name '%1!ws!' is not unique\n",
NetworkName
));
return(FALSE);
}
}
if (listHead == &(ConfigLists->InputConfigList)) {
listHead = &(ConfigLists->DeletedInterfaceList);
}
else if (listHead == &(ConfigLists->DeletedInterfaceList)) {
listHead = &(ConfigLists->UpdatedInterfaceList);
}
else if (listHead == &(ConfigLists->UpdatedInterfaceList)) {
listHead = &(ConfigLists->CreatedNetworkList);
}
else if (listHead == &(ConfigLists->CreatedNetworkList)) {
listHead = UnchangedConfigList;
}
else {
break;
}
}
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Net name '%1!ws!' is unique\n",
NetworkName
));
return(TRUE);
} // ClNetpIsNetworkNameUnique
LPWSTR
ClNetpMakeNetworkName(
IN LPWSTR OldNetworkName,
IN DWORD InstanceNumber
)
{
LPWSTR newName, endPtr, truncatePtr, ptr;
DWORD length, tempInstance, tempLength;
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Attempt to make net name '%1!ws!' unique by appending (%2!u!)\n",
OldNetworkName,
InstanceNumber
));
//
// Append (InstanceNumber) to name string
//
for (endPtr = OldNetworkName, length = 0;
*endPtr != UNICODE_NULL;
endPtr++, length++
);
//
// Check if there is already an instance number appended.
//
if ( (length > 3) && (*(endPtr - 1) == L')') ) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] There may already be an instance number appended to '%1!ws!'\n",
OldNetworkName
));
//
// Scan backwards looking for '('
//
for (ptr = endPtr - 2, tempLength = 0;
ptr != OldNetworkName;
ptr--, tempLength++
)
{
if (*ptr == L'(') {
//
// Looks promising. Check that all characters in between are
// numbers and that the string size is reasonable.
//
if ((tempLength == 0) || (tempLength > 3)) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Unsure net name %'1!ws!' contains an instance number - ignore.\n",
OldNetworkName
));
break;
}
truncatePtr = ptr;
for (ptr++; *ptr != L')'; ptr++) {
if ( (*ptr < L'0') || (*ptr > L'9') ) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Tail of net name '%1!ws!' is not an instance number\n",
OldNetworkName
));
break;
}
}
if (*ptr == L')') {
//
// This is an instance number. Truncate the string here.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Replacing old instance number '%1!ws!' appended to name '%2!ws!'\n",
truncatePtr,
OldNetworkName
));
*truncatePtr = UNICODE_NULL;
length -= tempLength + 2;
}
break;
}
}
}
//
// Count number of digits in instance number
//
for (tempInstance = InstanceNumber;
tempInstance > 0;
tempInstance /= 10, length++
);
//
// Account for '(', ')', and NULL
//
length += 3;
newName = LocalAlloc(LMEM_FIXED, length * sizeof(WCHAR));
if (newName == NULL) {
return(NULL);
}
wsprintfW(newName, L"%ws(%u)", OldNetworkName, InstanceNumber);
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] New net name is '%1!ws!'\n",
newName
));
return(newName);
} // ClNetpMakeNetworkName
LPWSTR
ClNetpMakeUniqueNetworkName(
IN LPWSTR ConnectoidName,
IN LPWSTR ConnectoidGuid,
IN PCLNET_CONFIG_LISTS ConfigLists,
IN PLIST_ENTRY UnchangedConfigList
)
{
BOOLEAN unique;
BOOLEAN updateConnectoid = FALSE;
LPWSTR newNetworkName;
DWORD index = 1;
newNetworkName = ClNetpCloneString(ConnectoidName);
if (newNetworkName == NULL) {
return(NULL);
}
do {
unique = ClNetpIsNetworkNameUnique(
newNetworkName,
ConfigLists,
UnchangedConfigList
);
if (!unique) {
LPWSTR oldNetworkName = newNetworkName;
newNetworkName = ClNetpMakeNetworkName(
oldNetworkName,
index++
);
LocalFree(oldNetworkName);
if (newNetworkName == NULL) {
return(NULL);
}
updateConnectoid = TRUE;
}
} while (!unique);
//
// Update the local connectoid name if necessary.
//
if (updateConnectoid) {
DWORD status;
ClNetDbgPrint((LOG_UNUSUAL,
"[ClNet] Changing name of connectoid '%1!ws!' to '%2!ws!' to "
"guarantee cluster-wide uniqueness\n",
ConnectoidName,
newNetworkName
));
status = ClRtlFindConnectoidByGuidAndSetName(
ConnectoidGuid,
newNetworkName
);
if (status != ERROR_SUCCESS) {
ClNetDbgPrint((LOG_UNUSUAL,
"[ClNet] Failed to change name of connectoid '%1!ws!' to "
"'%2!ws!', status %3!u!\n",
ConnectoidName,
newNetworkName,
status
));
}
}
return(newNetworkName);
} // ClNetpMakeUniqueNetworkName
DWORD
ClNetpUpdateConfigEntry(
PCLNET_CONFIG_ENTRY ConfigEntry,
LPWSTR Address,
LPWSTR AdapterId,
LPWSTR AdapterName,
LPWSTR NodeName,
LPWSTR NetworkName
)
{
LPWSTR newAddress = NULL;
LPWSTR newInterfaceName = NULL;
LPWSTR newAdapterId = NULL;
LPWSTR newAdapterName = NULL;
if (Address != NULL) {
newAddress = ClNetpCloneString(Address);
if (newAddress == NULL) {
goto error_exit;
}
}
if (AdapterId != NULL) {
newAdapterId = ClNetpCloneString(AdapterId);
if (newAdapterId == NULL) {
goto error_exit;
}
}
if (AdapterName != NULL) {
newAdapterName = ClNetpCloneString(AdapterName);
if (newAdapterName == NULL) {
goto error_exit;
}
}
if ( (NodeName != NULL) && (NetworkName != NULL) ) {
newInterfaceName = ClNetMakeInterfaceName(
NULL,
NodeName,
NetworkName
);
if (newInterfaceName == NULL) {
goto error_exit;
}
}
if (newAddress != NULL) {
LocalFree(ConfigEntry->InterfaceInfo.Address);
ConfigEntry->InterfaceInfo.Address = newAddress;
}
if (newAdapterId != NULL) {
LocalFree(ConfigEntry->InterfaceInfo.AdapterId);
ConfigEntry->InterfaceInfo.AdapterId = newAdapterId;
}
if (newAdapterName != NULL) {
LocalFree(ConfigEntry->InterfaceInfo.AdapterName);
ConfigEntry->InterfaceInfo.AdapterName = newAdapterName;
}
if (newInterfaceName != NULL) {
LocalFree(ConfigEntry->InterfaceInfo.Name);
ConfigEntry->InterfaceInfo.Name = newInterfaceName;
}
return(ERROR_SUCCESS);
error_exit:
if (newAddress != NULL) {
LocalFree(newAddress);
}
if (newAdapterId != NULL) {
LocalFree(newAdapterId);
}
if (newAdapterName != NULL) {
LocalFree(newAdapterName);
}
if (newInterfaceName != NULL) {
LocalFree(newInterfaceName);
}
return(ERROR_NOT_ENOUGH_MEMORY);
} // ClNetpUpdateConfigEntry
DWORD
ClNetpAllocConfigEntryInterface(
IN PCLNET_CONFIG_ENTRY ConfigEntry,
IN LPWSTR InterfaceId,
IN LPWSTR InterfaceName,
IN LPWSTR InterfaceDescription,
IN LPWSTR NodeId,
IN LPWSTR AdapterId,
IN LPWSTR AdapterName,
IN LPWSTR InterfaceAddress,
IN LPWSTR ClusnetEndpoint,
IN DWORD InterfaceState
)
{
PNM_INTERFACE_INFO2 interfaceInfo = &(ConfigEntry->InterfaceInfo);
if (InterfaceId != NULL) {
interfaceInfo->Id = ClNetpCloneString(InterfaceId);
if (interfaceInfo->Id == NULL) {
goto error_exit;
}
}
ConfigEntry->IsInterfaceInfoValid = TRUE;
if (InterfaceName != NULL) {
interfaceInfo->Name = ClNetpCloneString(InterfaceName);
if (interfaceInfo->Name == NULL) {
goto error_exit;
}
}
if (InterfaceDescription != NULL) {
interfaceInfo->Description = ClNetpCloneString(InterfaceDescription);
if (interfaceInfo->Description == NULL) {
goto error_exit;
}
}
if (NodeId != NULL) {
interfaceInfo->NodeId = ClNetpCloneString(NodeId);
if (interfaceInfo->NodeId == NULL) {
goto error_exit;
}
}
interfaceInfo->NetworkId = ClNetpCloneString(ConfigEntry->NetworkInfo.Id);
if (interfaceInfo->NetworkId == NULL) {
goto error_exit;
}
if (AdapterId != NULL) {
interfaceInfo->AdapterId = ClNetpCloneString(AdapterId);
if (interfaceInfo->AdapterId == NULL) {
goto error_exit;
}
}
if (AdapterName != NULL) {
interfaceInfo->AdapterName = ClNetpCloneString(AdapterName);
if (interfaceInfo->AdapterName == NULL) {
goto error_exit;
}
}
if (InterfaceAddress != NULL) {
interfaceInfo->Address = ClNetpCloneString(InterfaceAddress);
if (interfaceInfo->Address == NULL) {
goto error_exit;
}
}
if (ClusnetEndpoint != NULL) {
interfaceInfo->ClusnetEndpoint = ClNetpCloneString(ClusnetEndpoint);
if (interfaceInfo->ClusnetEndpoint == NULL) {
goto error_exit;
}
}
interfaceInfo->State = InterfaceState;
interfaceInfo->NetIndex = NmInvalidInterfaceNetIndex;
return(ERROR_SUCCESS);
error_exit:
ClNetFreeInterfaceInfo(&(ConfigEntry->InterfaceInfo));
ConfigEntry->IsInterfaceInfoValid = FALSE;
return(ERROR_NOT_ENOUGH_MEMORY);
} // ClNetpAllocConfigEntryInterface
DWORD
ClNetpAllocConfigEntryNetwork(
IN PCLNET_CONFIG_ENTRY ConfigEntry,
IN LPWSTR NetworkId,
IN LPWSTR NetworkName,
IN LPWSTR NetworkDescription,
IN DWORD NetworkRole,
IN DWORD NetworkPriority,
IN LPWSTR NetworkTransport,
IN LPWSTR NetworkAddress,
IN LPWSTR NetworkAddressMask
)
{
PNM_NETWORK_INFO networkInfo;
networkInfo = &(ConfigEntry->NetworkInfo);
if (NetworkId != NULL) {
networkInfo->Id = ClNetpCloneString(NetworkId);
if (networkInfo->Id == NULL) {
goto error_exit;
}
}
if (NetworkName != NULL) {
networkInfo->Name = ClNetpCloneString(NetworkName);
if (networkInfo->Name == NULL) {
goto error_exit;
}
}
if (NetworkDescription != NULL) {
networkInfo->Description = ClNetpCloneString(NetworkDescription);
if (networkInfo->Description == NULL) {
goto error_exit;
}
}
networkInfo->Role = NetworkRole;
networkInfo->Priority = NetworkPriority;
if (NetworkTransport != NULL) {
networkInfo->Transport = ClNetpCloneString(NetworkTransport);
if (networkInfo->Transport == NULL) {
goto error_exit;
}
}
if (NetworkAddress != NULL) {
networkInfo->Address = ClNetpCloneString(NetworkAddress);
if (networkInfo->Address == NULL) {
goto error_exit;
}
}
if (NetworkAddressMask != NULL) {
networkInfo->AddressMask = ClNetpCloneString(NetworkAddressMask);
if (networkInfo->AddressMask == NULL) {
goto error_exit;
}
}
return(ERROR_SUCCESS);
error_exit:
ClNetFreeConfigEntry(ConfigEntry);
return(ERROR_NOT_ENOUGH_MEMORY);
} // ClNetpAllocConfigEntryNetwork
DWORD
ClNetpCreateConfigEntryInterface(
PCLNET_CONFIG_ENTRY ConfigEntry,
LPWSTR NodeName,
LPWSTR NodeId,
PCLRTL_NET_ADAPTER_INFO AdapterInfo,
PCLRTL_NET_INTERFACE_INFO AdapterIfInfo,
LPWSTR ClusnetEndpoint
)
{
LPWSTR id;
LPWSTR name;
DWORD status = ERROR_NOT_ENOUGH_MEMORY;
id = ClRtlMakeGuid();
if (id != NULL) {
name = ClNetMakeInterfaceName(
NULL,
NodeName,
ConfigEntry->NetworkInfo.Name
);
if (name != NULL) {
status = ClNetpAllocConfigEntryInterface(
ConfigEntry,
NULL, // Id
NULL, // Name
ClNetpEmptyString, // Description
NodeId,
AdapterInfo->DeviceGuid,
AdapterInfo->DeviceName,
AdapterIfInfo->InterfaceAddressString,
ClusnetEndpoint,
ClusterNetInterfaceUnavailable
);
if (status == ERROR_SUCCESS) {
ConfigEntry->InterfaceInfo.Id = id;
ConfigEntry->InterfaceInfo.Name = name;
return(ERROR_SUCCESS);
}
LocalFree(name);
}
LocalFree(id);
}
return(status);
} // ClNetpCreateInterface
PCLNET_CONFIG_ENTRY
ClNetpCreateConfigEntry(
LPWSTR NodeName,
LPWSTR NodeId,
LPWSTR NetworkName,
DWORD NetworkRole,
DWORD NetworkPriority,
PCLRTL_NET_ADAPTER_INFO AdapterInfo,
PCLRTL_NET_INTERFACE_INFO AdapterIfInfo,
LPWSTR ClusnetEndpoint
)
{
PCLNET_CONFIG_ENTRY newEntry;
DWORD status;
newEntry = LocalAlloc(
(LMEM_FIXED | LMEM_ZEROINIT),
sizeof(CLNET_CONFIG_ENTRY)
);
if (newEntry == NULL) {
return(NULL);
}
newEntry->NetworkInfo.Id = ClRtlMakeGuid();
if (newEntry->NetworkInfo.Id == NULL) {
goto error_exit;
}
newEntry->NetworkInfo.Name = ClNetpCloneString(NetworkName);
if (newEntry->NetworkInfo.Name == NULL) {
goto error_exit;
}
status = ClNetpCreateConfigEntryInterface(
newEntry,
NodeName,
NodeId,
AdapterInfo,
AdapterIfInfo,
ClusnetEndpoint
);
if (status != ERROR_SUCCESS) {
goto error_exit;
}
status = ClNetpAllocConfigEntryNetwork(
newEntry,
NULL, // NetworkId
NULL, // NetworkName
ClNetpEmptyString, // Description
NetworkRole,
NetworkPriority,
L"Tcpip",
AdapterIfInfo->NetworkAddressString,
AdapterIfInfo->NetworkMaskString
);
if (status == ERROR_SUCCESS) {
return(newEntry);
}
error_exit:
ClNetFreeConfigEntry(newEntry);
LocalFree(newEntry);
return(NULL);
} // ClNetpCreateConfigEntry
DWORD
ClNetpCopyNetworkInfo(
IN PNM_NETWORK_INFO DstInfo,
IN PNM_NETWORK_INFO SrcInfo
)
{
DWORD status = ERROR_SUCCESS;
try {
DstInfo->Id = ClNetCopyString(SrcInfo->Id, TRUE);
DstInfo->Name = ClNetCopyString(SrcInfo->Name, TRUE);
DstInfo->Description = ClNetCopyString(SrcInfo->Description, TRUE);
DstInfo->Role = SrcInfo->Role;
DstInfo->Priority = SrcInfo->Priority;
DstInfo->Transport = ClNetCopyString(SrcInfo->Transport, TRUE);
DstInfo->Address = ClNetCopyString(SrcInfo->Address, TRUE);
DstInfo->AddressMask = ClNetCopyString(SrcInfo->AddressMask, TRUE);
DstInfo->Ignore = FALSE;
} except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
ClNetFreeNetworkInfo(DstInfo);
}
return(status);
} // ClNetpCopyNetworkInfo
DWORD
ClNetpCopyInterfaceInfo(
IN PNM_INTERFACE_INFO2 DstInfo,
IN PNM_INTERFACE_INFO2 SrcInfo
)
{
DWORD status = ERROR_SUCCESS;
try {
DstInfo->Id = ClNetCopyString(SrcInfo->Id, TRUE);
DstInfo->Name = ClNetCopyString(SrcInfo->Name, TRUE);
DstInfo->Description = ClNetCopyString(SrcInfo->Description, TRUE);
DstInfo->NodeId = ClNetCopyString(SrcInfo->NodeId, TRUE);
DstInfo->NetworkId = ClNetCopyString(SrcInfo->NetworkId, TRUE);
DstInfo->AdapterName = ClNetCopyString(SrcInfo->AdapterName, TRUE);
DstInfo->Address = ClNetCopyString(SrcInfo->Address, TRUE);
DstInfo->ClusnetEndpoint = ClNetCopyString(
SrcInfo->ClusnetEndpoint,
TRUE
);
DstInfo->State = SrcInfo->State;
DstInfo->Ignore = FALSE;
DstInfo->AdapterId = ClNetCopyString(SrcInfo->AdapterId, TRUE);
DstInfo->NetIndex = SrcInfo->NetIndex;
} except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
ClNetFreeInterfaceInfo(DstInfo);
}
return(status);
} // ClNetpCopyInterfaceInfo
//////////////////////////////////////////////////////////////////////////////
//
// Public routines
//
//////////////////////////////////////////////////////////////////////////////
VOID
ClNetInitialize(
IN LPFN_CLNETPRINT pfnPrint,
IN LPFN_CLNETLOGEVENT pfnLogEvent,
IN LPFN_CLNETLOGEVENT1 pfnLogEvent1,
IN LPFN_CLNETLOGEVENT2 pfnLogEvent2,
IN LPFN_CLNETLOGEVENT3 pfnLogEvent3
)
{
pClNetPrint = pfnPrint;
pClNetLogEvent = pfnLogEvent;
pClNetLogEvent1 = pfnLogEvent1;
pClNetLogEvent2 = pfnLogEvent2;
pClNetLogEvent3 = pfnLogEvent3;
} // ClNetInitialize
LPWSTR
ClNetCopyString(
IN LPWSTR SourceString,
IN BOOL RaiseExceptionOnError
)
{
LPWSTR str;
str = (LPWSTR) MIDL_user_allocate(
(lstrlenW(SourceString) + 1) * sizeof(WCHAR)
);
if (str != NULL) {
lstrcpyW(str, SourceString);
}
else if (RaiseExceptionOnError) {
RaiseException(ERROR_NOT_ENOUGH_MEMORY, 0, 0, NULL);
}
return(str);
} // ClNetCopyString
VOID
ClNetInitializeConfigLists(
PCLNET_CONFIG_LISTS Lists
)
{
InitializeListHead(&(Lists->InputConfigList));
InitializeListHead(&(Lists->DeletedInterfaceList));
InitializeListHead(&(Lists->UpdatedInterfaceList));
InitializeListHead(&(Lists->CreatedInterfaceList));
InitializeListHead(&(Lists->CreatedNetworkList));
return;
} // ClNetInitializeConfigLists
DWORD
ClNetConvertEnumsToConfigList(
IN PNM_NETWORK_ENUM * NetworkEnum,
IN PNM_INTERFACE_ENUM2 * InterfaceEnum,
IN LPWSTR LocalNodeId,
IN OUT PLIST_ENTRY ConfigList,
IN BOOLEAN DeleteEnums
)
{
DWORD i, j;
DWORD status;
PNM_NETWORK_INFO network;
PNM_INTERFACE_INFO2 netInterface;
PCLNET_CONFIG_ENTRY configEntry;
InitializeListHead(ConfigList);
for (i=0; i<(*NetworkEnum)->NetworkCount; i++) {
network = &((*NetworkEnum)->NetworkList[i]);
configEntry = LocalAlloc(
(LMEM_FIXED | LMEM_ZEROINIT),
sizeof(CLNET_CONFIG_ENTRY)
);
if (configEntry == NULL) {
status = ERROR_NOT_ENOUGH_MEMORY;
goto error_exit;
}
if (DeleteEnums) {
CopyMemory(
&(configEntry->NetworkInfo),
network,
sizeof(NM_NETWORK_INFO)
);
}
else {
status = ClNetpCopyNetworkInfo(
&(configEntry->NetworkInfo),
network
);
if (status != ERROR_SUCCESS) {
goto error_exit;
}
}
for (j=0; j<(*InterfaceEnum)->InterfaceCount; j++) {
netInterface = &((*InterfaceEnum)->InterfaceList[j]);
if ( (netInterface->Ignore == FALSE) &&
(lstrcmpiW(netInterface->NetworkId, network->Id) == 0) &&
(lstrcmpiW(netInterface->NodeId, LocalNodeId) == 0)
)
{
if (DeleteEnums) {
CopyMemory(
&(configEntry->InterfaceInfo),
netInterface,
sizeof(NM_INTERFACE_INFO2)
);
}
else {
status = ClNetpCopyInterfaceInfo(
&(configEntry->InterfaceInfo),
netInterface
);
if (status != ERROR_SUCCESS) {
goto error_exit;
}
}
configEntry->IsInterfaceInfoValid = TRUE;
if ( DeleteEnums ) {
ZeroMemory(netInterface, sizeof(NM_INTERFACE_INFO2));
}
netInterface->Ignore = TRUE;
break;
}
}
InsertTailList(ConfigList, &(configEntry->Linkage));
if ( DeleteEnums ) {
ZeroMemory(network, sizeof(NM_NETWORK_INFO));
}
}
status = ERROR_SUCCESS;
error_exit:
if ( DeleteEnums ) {
ClNetFreeNetworkEnum(*NetworkEnum); *NetworkEnum = NULL;
ClNetFreeInterfaceEnum(*InterfaceEnum); *InterfaceEnum = NULL;
}
if (status != ERROR_SUCCESS) {
ClNetFreeConfigList(ConfigList);
}
return(status);
} // ClNetConvertEnumsToConfigList
VOID
ClNetFreeNetworkEnum(
IN PNM_NETWORK_ENUM NetworkEnum
)
/*++
Routine Description:
Frees a network enumeration structure.
Arguments:
NetworkEnum - A pointer to the network enumeration structure to free.
Return Value:
None.
--*/
{
DWORD i;
for (i=0; i<NetworkEnum->NetworkCount; i++) {
ClNetFreeNetworkInfo(&(NetworkEnum->NetworkList[i]));
}
MIDL_user_free(NetworkEnum);
return;
} // ClNetFreeNetworkEnum
VOID
ClNetFreeNetworkInfo(
IN PNM_NETWORK_INFO NetworkInfo
)
/*++
Routine Description:
Frees a network information structure or a linked list of network
information structures.
Arguments:
NetworkInfo - A pointer to the network information structure
to free.
Return Value:
None.
--*/
{
if (NetworkInfo->Id != NULL) {
MIDL_user_free(NetworkInfo->Id);
NetworkInfo->Id = NULL;
}
if (NetworkInfo->Name != NULL) {
MIDL_user_free(NetworkInfo->Name);
NetworkInfo->Name = NULL;
}
if (NetworkInfo->Description != NULL) {
MIDL_user_free(NetworkInfo->Description);
NetworkInfo->Description = NULL;
}
if (NetworkInfo->Transport != NULL) {
MIDL_user_free(NetworkInfo->Transport);
NetworkInfo->Transport = NULL;
}
if (NetworkInfo->Address != NULL) {
MIDL_user_free(NetworkInfo->Address);
NetworkInfo->Address = NULL;
}
if (NetworkInfo->AddressMask != NULL) {
MIDL_user_free(NetworkInfo->AddressMask);
NetworkInfo->AddressMask = NULL;
}
return;
} // ClNetFreeNetworkInfo
VOID
ClNetFreeInterfaceEnum1(
IN PNM_INTERFACE_ENUM InterfaceEnum1
)
/*++
Routine Description:
Frees a interface enumeration structure.
Arguments:
InterfaceEnum - A pointer to the interface enumeration structure
to free.
Return Value:
None.
--*/
{
DWORD i;
for (i=0; i<InterfaceEnum1->InterfaceCount; i++) {
ClNetFreeInterfaceInfo(
(PNM_INTERFACE_INFO2) &(InterfaceEnum1->InterfaceList[i])
);
}
MIDL_user_free(InterfaceEnum1);
return;
} // ClNetFreeInterfaceEnum
VOID
ClNetFreeInterfaceEnum(
IN PNM_INTERFACE_ENUM2 InterfaceEnum
)
/*++
Routine Description:
Frees a interface enumeration structure.
Arguments:
InterfaceEnum - A pointer to the interface enumeration structure
to free.
Return Value:
None.
--*/
{
DWORD i;
for (i=0; i<InterfaceEnum->InterfaceCount; i++) {
ClNetFreeInterfaceInfo(&(InterfaceEnum->InterfaceList[i]));
}
MIDL_user_free(InterfaceEnum);
return;
} // ClNetFreeInterfaceEnum
VOID
ClNetFreeInterfaceInfo(
IN PNM_INTERFACE_INFO2 InterfaceInfo
)
/*++
Routine Description:
Frees a network interface information strucuture.
Arguments:
InterfaceInfo - A pointer to the interface information
structure to free.
Return Value:
None.
--*/
{
if (InterfaceInfo->Id != NULL) {
MIDL_user_free(InterfaceInfo->Id);
InterfaceInfo->Id = NULL;
}
if (InterfaceInfo->Name != NULL) {
MIDL_user_free(InterfaceInfo->Name);
InterfaceInfo->Name = NULL;
}
if (InterfaceInfo->Description != NULL) {
MIDL_user_free(InterfaceInfo->Description);
InterfaceInfo->Description = NULL;
}
if (InterfaceInfo->NetworkId != NULL) {
MIDL_user_free(InterfaceInfo->NetworkId);
InterfaceInfo->NetworkId = NULL;
}
if (InterfaceInfo->NodeId != NULL) {
MIDL_user_free(InterfaceInfo->NodeId);
InterfaceInfo->NodeId = NULL;
}
if (InterfaceInfo->AdapterId != NULL) {
MIDL_user_free(InterfaceInfo->AdapterId);
InterfaceInfo->AdapterId = NULL;
}
if (InterfaceInfo->AdapterName != NULL) {
MIDL_user_free(InterfaceInfo->AdapterName);
InterfaceInfo->AdapterName = NULL;
}
if (InterfaceInfo->Address != NULL) {
MIDL_user_free(InterfaceInfo->Address);
InterfaceInfo->Address = NULL;
}
if (InterfaceInfo->ClusnetEndpoint != NULL) {
MIDL_user_free(InterfaceInfo->ClusnetEndpoint);
InterfaceInfo->ClusnetEndpoint = NULL;
}
return;
} // ClNetFreeInterfaceInfo
VOID
ClNetFreeNodeEnum1(
IN PNM_NODE_ENUM NodeEnum1
)
/*++
Routine Description:
Frees a node enumeration structure.
Arguments:
NodeEnum - A pointer to the node enumeration structure to free.
Return Value:
None.
--*/
{
DWORD i;
for (i=0; i<NodeEnum1->NodeCount; i++) {
ClNetFreeNodeInfo(
(PNM_NODE_INFO2) &(NodeEnum1->NodeList[i])
);
}
MIDL_user_free(NodeEnum1);
return;
} // NmpFreeNodeEnum1
VOID
ClNetFreeNodeEnum(
IN PNM_NODE_ENUM2 NodeEnum
)
/*++
Routine Description:
Frees a node enumeration structure.
Arguments:
NodeEnum - A pointer to the node enumeration structure to free.
Return Value:
None.
--*/
{
DWORD i;
for (i=0; i<NodeEnum->NodeCount; i++) {
ClNetFreeNodeInfo(&(NodeEnum->NodeList[i]));
}
MIDL_user_free(NodeEnum);
return;
} // NmpFreeNodeEnum
VOID
ClNetFreeNodeInfo(
IN PNM_NODE_INFO2 NodeInfo
)
/*++
Routine Description:
Frees a node information structure.
Arguments:
NodeInfo - A pointer to the node information structure to free.
Return Value:
None.
--*/
{
//
// Currently nothing to free.
//
return;
} // NmpFreeNodeInfo
VOID
ClNetFreeConfigEntry(
PCLNET_CONFIG_ENTRY ConfigEntry
)
{
ClNetFreeNetworkInfo(&(ConfigEntry->NetworkInfo));
if (ConfigEntry->IsInterfaceInfoValid) {
ClNetFreeInterfaceInfo(&(ConfigEntry->InterfaceInfo));
}
return;
} // ClNetFreeConfigEntry
VOID
ClNetFreeConfigList(
IN PLIST_ENTRY ConfigList
)
{
PLIST_ENTRY listEntry;
PCLNET_CONFIG_ENTRY configEntry;
while (!IsListEmpty(ConfigList)) {
listEntry = RemoveHeadList(ConfigList);
configEntry = CONTAINING_RECORD(
listEntry,
CLNET_CONFIG_ENTRY,
Linkage
);
ClNetFreeConfigEntry(configEntry);
}
return;
} // ClNetFreeConfigList
VOID
ClNetFreeConfigLists(
PCLNET_CONFIG_LISTS ConfigLists
)
{
ClNetFreeConfigList(&(ConfigLists->InputConfigList));
ClNetFreeConfigList(&(ConfigLists->DeletedInterfaceList));
ClNetFreeConfigList(&(ConfigLists->UpdatedInterfaceList));
ClNetFreeConfigList(&(ConfigLists->CreatedInterfaceList));
ClNetFreeConfigList(&(ConfigLists->CreatedNetworkList));
return;
} // ClNetFreeConfigLists
LPWSTR
ClNetMakeInterfaceName(
LPWSTR Prefix, OPTIONAL
LPWSTR NodeName,
LPWSTR NetworkName
)
/*++
Construct a name of the form "<network name> - <node name>".
Code in cluscfg.exe depends on this form. If you change this,
you need to change the code in setup\cluscfg\netadptr.cpp as
well
--*/
{
WCHAR text[] = L" - ";
LPWSTR name;
DWORD nameLength = 0;
if (Prefix != NULL) {
nameLength += lstrlenW(Prefix);
}
nameLength += lstrlenW(text) + lstrlenW(NodeName) +
lstrlenW(NetworkName) + 1;
nameLength *= sizeof(WCHAR);
name = MIDL_user_allocate(nameLength);
if (name != NULL) {
name[0] = UNICODE_NULL;
if (Prefix != NULL) {
lstrcatW(name, Prefix);
}
lstrcatW(name, NetworkName);
lstrcatW(name, text);
lstrcatW(name, NodeName);
return(name);
}
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return(NULL);
} // ClNetMakeInterfaceName
DWORD
ClNetConfigureNetworks(
IN LPWSTR LocalNodeId,
IN LPWSTR LocalNodeName,
IN LPWSTR DefaultClusnetEndpoint,
IN CLUSTER_NETWORK_ROLE DefaultNetworkRole,
IN BOOL NetNameHasPrecedence,
IN OUT PCLNET_CONFIG_LISTS ConfigLists,
IN OUT LPDWORD MatchedNetworkCount,
IN OUT LPDWORD NewNetworkCount
)
/*++
Notes:
NetNameHasPrecedence is TRUE if connectoid names should be changed to
align with the name in the NM_NETWORK_INFO struct. Otherwise the name of
network object is changed to match the connectoid name.
Output interface lists must be processed in the following order to
guarantee correctness:
1 - DeletedInterfaceList
2 - UpdatedInterfaceList
3 - CreatedInterfaceList
4 - CreatedNetworkList
--*/
{
DWORD status = ERROR_SUCCESS;
PCLRTL_NET_ADAPTER_ENUM adapterEnum = NULL;
PCLRTL_NET_ADAPTER_INFO adapterInfo = NULL;
PCLRTL_NET_INTERFACE_INFO adapterIfInfo = NULL;
WCHAR errorString[12];
DWORD eventCode = 0;
DWORD hiddenAdapterCount = 0;
PLIST_ENTRY listEntry;
PCLNET_CONFIG_ENTRY configEntry;
PNM_NETWORK_INFO networkInfo;
PNM_INTERFACE_INFO2 interfaceInfo;
LIST_ENTRY unchangedConfigList;
DWORD matchedNetworkCount = 0;
DWORD newNetworkCount = 0;
BOOLEAN newAdapter;
ClNetDbgPrint((LOG_NOISE, "[ClNet] Configuring networks...\n"));
if (NetNameHasPrecedence) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Cluster network names have precedence over "
"local connection object names.\n"
));
}
else {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Local connection object names have precedence "
"over cluster network names.\n"
));
}
InitializeListHead(&unchangedConfigList);
//
// Obtain the network configuration for the local system.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Querying local network configuration.\n"
));
adapterEnum = ClRtlEnumNetAdapters();
if (adapterEnum == NULL) {
status = GetLastError();
wsprintfW(&(errorString[0]), L"%u", status);
(*pClNetLogEvent1)(
LOG_CRITICAL,
CLNET_EVENT_QUERY_CONFIG_FAILED,
errorString
);
ClNetDbgPrint((
LOG_CRITICAL,
"[ClNet] Failed to obtain local system network config, "
"status %1!u!.\n",
status
));
return(status);
}
//
// Ignore all adapters which are hidden or have an address of 0.0.0.0.
//
for (adapterInfo = adapterEnum->AdapterList;
adapterInfo != NULL;
adapterInfo = adapterInfo->Next
)
{
if (adapterInfo->Flags & CLRTL_NET_ADAPTER_HIDDEN) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Ignoring hidden adapter '%1!ws!' (%2!ws!).\n",
adapterInfo->DeviceName,
adapterInfo->DeviceGuid
));
adapterInfo->Ignore = TRUE;
hiddenAdapterCount++;
}
else {
adapterIfInfo = ClRtlGetPrimaryNetInterface(adapterInfo);
if (adapterIfInfo != NULL) {
if (adapterIfInfo->InterfaceAddress == 0) {
(*pClNetLogEvent1)(
LOG_UNUSUAL,
CLNET_EVENT_INVALID_ADAPTER_ADDRESS,
adapterInfo->DeviceName
);
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Ignoring adapter '%1!ws!' "
"(%2!ws!) because its"
"primary address is 0.0.0.0.\n",
adapterInfo->DeviceName,
adapterInfo->DeviceGuid
));
adapterInfo->Ignore = TRUE;
hiddenAdapterCount++;
}
}
else {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Ignoring adapter '%1!ws!' "
"(%2!ws!) because its primary net "
"interface could not be found.\n",
adapterInfo->DeviceName,
adapterInfo->DeviceGuid
));
adapterInfo->Ignore = TRUE;
hiddenAdapterCount++;
}
}
}
if ((adapterEnum->AdapterCount - hiddenAdapterCount) == 0) {
(*pClNetLogEvent)(
LOG_UNUSUAL,
CLNET_EVENT_NO_VALID_ADAPTER
);
ClNetDbgPrint((
LOG_CRITICAL,
"[ClNet] No usable network adapters are installed in this "
"system.\n"
));
}
//
// Phase 1
//
// Validate existing interface definitions for this node
// and update as needed.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Phase 1 - Examining previous network definitions.\n"
));
//
// Walk all of the network definitions and examine the corresponding
// interface definitions for this node.
//
while (!IsListEmpty(&(ConfigLists->InputConfigList))) {
configEntry = CONTAINING_RECORD(
ConfigLists->InputConfigList.Flink,
CLNET_CONFIG_ENTRY,
Linkage
);
networkInfo = &(configEntry->NetworkInfo);
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Examining cluster network '%1!ws!' (%2!ws!).\n",
networkInfo->Name,
networkInfo->Id
));
//
// Check if there is an existing interface definition for
// this node on this network.
//
if (configEntry->IsInterfaceInfoValid) {
// An interface definition already exists for this node on
// the network. We will either find an installed adapter for it
// or delete the interface.
//
interfaceInfo = &(configEntry->InterfaceInfo);
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] This node was attached to the network by "
"adapter '%1!ws!', (%2!ws!).\n",
interfaceInfo->AdapterName,
interfaceInfo->AdapterId
));
//
// Try to find the adapter specified in the interface
// definition. If it is still attached to the network,
// then we want to reuse it.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Checking if adapter '%1!ws!' is still installed.\n",
interfaceInfo->AdapterName
));
adapterInfo = ClRtlFindNetAdapterById(
adapterEnum,
interfaceInfo->AdapterId
);
if (adapterInfo != NULL) {
//
// Found the specified adapter. Check if this
// adapter is still attached to the network by
// comparing network address values.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Adapter '%1!ws!' is still installed, checking "
"if it is still attached to the same network.\n",
adapterInfo->DeviceName
));
adapterIfInfo = ClRtlFindNetInterfaceByNetworkAddress(
adapterInfo,
networkInfo->Address
);
if (adapterIfInfo != NULL) {
//
// The adapter is still attached to this network.
//
newAdapter = FALSE;
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Adapter '%1!ws!' is still attached to "
"network %2!ws!.\n",
interfaceInfo->AdapterName,
networkInfo->Name
));
}
else {
//
// The adapter is no longer attached to this network.
//
adapterInfo = NULL;
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Adapter '%1!ws!' is no longer attached "
"to network %2!ws!.\n",
interfaceInfo->AdapterName,
networkInfo->Name
));
}
}
else {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Adapter '%1!ws!' is no longer available.\n",
interfaceInfo->AdapterName
));
}
//
// If the old adapter was removed or is now attached to a
// different network, search for a new adapter that is
// attached to the network.
//
if (adapterInfo == NULL) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Searching for a new adapter which is attached "
"to network '%1!ws!'.\n",
networkInfo->Name
));
adapterIfInfo = NULL;
adapterInfo = ClRtlFindNetAdapterByNetworkAddress(
adapterEnum,
networkInfo->Address,
&adapterIfInfo
);
if (adapterInfo != NULL) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Adapter '%1!ws!' (%2!ws!) is attached to "
"network '%3!ws!'.\n",
interfaceInfo->AdapterName,
interfaceInfo->AdapterId,
networkInfo->Name
));
newAdapter = TRUE;
}
}
//
// If we found an adapter, old or new, which is attached to this
// network, update the interface definition, as needed.
//
if (adapterInfo != NULL) {
BOOLEAN somethingChanged = FALSE;
BOOL netNameHasPrecedence = NetNameHasPrecedence;
LPWSTR address = NULL;
LPWSTR adapterName = NULL;
LPWSTR adapterId = NULL;
LPWSTR networkName = NULL;
if (newAdapter) {
netNameHasPrecedence = TRUE;
adapterId = adapterInfo->DeviceGuid;
somethingChanged = TRUE;
}
//
// If the address value has changed, update it
//
if (lstrcmpW(
interfaceInfo->Address,
adapterIfInfo->InterfaceAddressString
) != 0
)
{
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] The address for the network interface has "
"changed to %1!ws!.\n",
adapterIfInfo->InterfaceAddressString
));
address = adapterIfInfo->InterfaceAddressString;
somethingChanged = TRUE;
}
//
// If the adapter name changed, update it.
//
if (lstrcmpW(
interfaceInfo->AdapterName,
adapterInfo->DeviceName
) != 0
)
{
if (!newAdapter) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] The adapter name for the network "
"interface has changed to '%1!ws!'.\n",
adapterInfo->DeviceName
));
}
adapterName = adapterInfo->DeviceName;
somethingChanged = TRUE;
}
//
// If the connectoid name is different, choose the correct
// name based on the name precedence and update the
// network, connectoid, and interface names as
// appropriate.
//
if (lstrcmpW(
networkInfo->Name,
adapterInfo->ConnectoidName
) != 0
)
{
if (netNameHasPrecedence) {
//
// Update the local connectoid name.
//
DWORD status;
ClNetDbgPrint((LOG_NOISE,
"[ClNet] Changing name of connectoid '%1!ws!' "
"(%2!ws!) to match name of cluster "
"network '%3!ws'\n",
adapterInfo->ConnectoidName,
adapterInfo->DeviceGuid,
networkInfo->Name
));
status = ClRtlFindConnectoidByGuidAndSetName(
adapterInfo->DeviceGuid,
networkInfo->Name
);
if ( status != ERROR_SUCCESS ) {
ClNetDbgPrint((LOG_UNUSUAL,
"[ClNet] Failed to change name of "
"connectoid from '%1!ws!' to '%2!ws!', "
"status %3!u!\n",
adapterInfo->ConnectoidName,
networkInfo->Name,
status
));
}
}
else {
//
// Update the network name. The connectoid name
// may get tweaked for uniqueness as a side
// effect.
//
ClNetDbgPrint((LOG_UNUSUAL,
"[ClNet] Changing name of cluster "
"network '%1!ws!' (%2!ws!) to match name of "
"connectoid '%3!ws!'.\n",
networkInfo->Name,
networkInfo->Id,
adapterInfo->ConnectoidName
));
networkName = ClNetpMakeUniqueNetworkName(
adapterInfo->ConnectoidName,
adapterInfo->DeviceGuid,
ConfigLists,
&unchangedConfigList
);
if (networkName == NULL) {
status = ERROR_NOT_ENOUGH_MEMORY;
goto error_exit;
}
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Changed name of cluster "
"network '%1!ws!' (%2!ws!) to '%3!ws!'.\n",
networkInfo->Name,
networkInfo->Id,
networkName
));
LocalFree(networkInfo->Name);
networkInfo->Name = networkName;
configEntry->UpdateNetworkName = TRUE;
somethingChanged = TRUE;
}
}
if (somethingChanged) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Updating configuration info for "
"interface '%1!ws!' (%2!ws!).\n",
interfaceInfo->Name,
interfaceInfo->Id
));
status = ClNetpUpdateConfigEntry(
configEntry,
address,
adapterId,
adapterName,
LocalNodeName,
networkName
);
if (status != ERROR_SUCCESS) {
goto error_exit;
}
//
// Move the entry to the updated interface list
//
RemoveEntryList(&(configEntry->Linkage));
InsertTailList(
&(ConfigLists->UpdatedInterfaceList),
&(configEntry->Linkage)
);
}
else {
//
// Move the entry to the unchanged list
//
RemoveEntryList(&(configEntry->Linkage));
InsertTailList(
&unchangedConfigList,
&(configEntry->Linkage)
);
}
}
else {
//
// This node is no longer attached to this network.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] This node is no longer attached to "
"network '%1!ws!' (%2!ws!).\n",
networkInfo->Name,
networkInfo->Id
));
(*pClNetLogEvent3)(
LOG_NOISE,
CLNET_EVENT_DELETE_INTERFACE,
networkInfo->Name,
interfaceInfo->AdapterName,
interfaceInfo->Name
);
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Deleting interface '%1!ws!' (%2!ws!) from the "
"cluster configuration.\n",
interfaceInfo->Name,
interfaceInfo->Id
));
//
// Move the entry to the deleted interface list.
//
RemoveEntryList(&(configEntry->Linkage));
InsertTailList(
&(ConfigLists->DeletedInterfaceList),
&(configEntry->Linkage)
);
}
}
else {
//
// This node was not previously attached to this network.
// Search for a new attachment.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] This node was not previously attached to "
"network '%1!ws!' (%2!ws!).\n",
networkInfo->Name,
networkInfo->Id
));
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Searching for a new attachment...\n"
));
adapterInfo = ClRtlFindNetAdapterByNetworkAddress(
adapterEnum,
networkInfo->Address,
&adapterIfInfo
);
if (adapterInfo != NULL) {
//
// Found a new adapter which is attached to this network.
// Create a new interface definition for it.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Adapter '%1!ws!' (%2!ws!) is attached to "
"network %3!ws!.\n",
adapterInfo->DeviceName,
adapterInfo->DeviceGuid,
networkInfo->Name
));
//
// Network name has precedence.
// Update the local connectoid name if necessary.
//
if (lstrcmpW(
networkInfo->Name,
adapterInfo->ConnectoidName
) != 0
)
{
DWORD status;
ClNetDbgPrint((LOG_NOISE,
"[ClNet] Changing name of connectoid '%1!ws!' (%2!ws!) "
"to match name of cluster network '%3!ws!'\n",
adapterInfo->ConnectoidName,
adapterInfo->DeviceGuid,
networkInfo->Name
));
status = ClRtlFindConnectoidByGuidAndSetName(
adapterInfo->DeviceGuid,
networkInfo->Name
);
if ( status != ERROR_SUCCESS ) {
ClNetDbgPrint((
LOG_UNUSUAL,
"[ClNet] Failed to change name of connectoid "
"'%1!ws!' (%2!ws!) to '%3!ws!', status %4!u!.\n",
adapterInfo->ConnectoidName,
adapterInfo->DeviceGuid,
networkInfo->Name,
status
));
}
}
status = ClNetpCreateConfigEntryInterface(
configEntry,
LocalNodeName,
LocalNodeId,
adapterInfo,
adapterIfInfo,
DefaultClusnetEndpoint
);
if (status != ERROR_SUCCESS) {
goto error_exit;
}
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Created cluster interface '%1!ws!' (%2!ws!).\n",
configEntry->InterfaceInfo.Name,
configEntry->InterfaceInfo.Id
));
//
// Put the entry on the created interface list
//
RemoveEntryList(&(configEntry->Linkage));
InsertTailList(
&(ConfigLists->CreatedInterfaceList),
&(configEntry->Linkage)
);
}
else {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] This node is not attached to network '%1!ws!'.\n",
networkInfo->Name
));
//
// Move the entry to the unchanged list
//
RemoveEntryList(&(configEntry->Linkage));
InsertTailList(&unchangedConfigList, &(configEntry->Linkage));
}
}
//
// If we found an adapter on this network, then mark it as
// consumed.
//
if (adapterInfo != NULL) {
//
// Consume the adapter
adapterInfo->Ignore = TRUE;
//
//
// Consume all other adapters that are attached to this
// network
//
ClNetpConsumeAdaptersOnNetwork(
adapterEnum,
adapterIfInfo->NetworkAddressString
);
matchedNetworkCount++;
}
}
//
// Phase 2
//
// Create new networks for any remaining adapters.
//
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Phase 2 - Creating new networks for all remaining "
"adapters.\n"
));
for (adapterInfo = adapterEnum->AdapterList;
adapterInfo != NULL;
adapterInfo = adapterInfo->Next
)
{
if ( !adapterInfo->Ignore && (adapterInfo->InterfaceCount > 0) ) {
LPWSTR newNetworkName;
(*pClNetLogEvent1)(
LOG_NOISE,
CLNET_EVENT_CREATE_NETWORK,
adapterInfo->ConnectoidName
);
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Creating new network & interface for "
"adapter '%1!ws!'.\n",
adapterInfo->DeviceName
));
//
// Create a unique network name based on the connectoid name.
// The connectoid name may get tweaked for uniqueness as a
// side effect.
//
newNetworkName = ClNetpMakeUniqueNetworkName(
adapterInfo->ConnectoidName,
adapterInfo->DeviceGuid,
ConfigLists,
&unchangedConfigList
);
if (newNetworkName == NULL) {
status = ERROR_NOT_ENOUGH_MEMORY;
goto error_exit;
}
adapterIfInfo = ClRtlGetPrimaryNetInterface(adapterInfo);
if (adapterIfInfo == NULL) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Not creating network for adapter "
" '%1!ws!' (%2!ws!) because its primary net "
"interface could not be found.\n",
adapterInfo->DeviceName,
adapterInfo->DeviceGuid
));
LocalFree(newNetworkName);
goto error_exit;
}
configEntry = ClNetpCreateConfigEntry(
LocalNodeName,
LocalNodeId,
newNetworkName,
DefaultNetworkRole,
CLNET_DEFAULT_NETWORK_PRIORITY,
adapterInfo,
adapterIfInfo,
DefaultClusnetEndpoint
);
LocalFree(newNetworkName);
if (configEntry == NULL) {
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Failed to create new network & interface "
"for adapter '%1!ws!' (%2!ws!)\n",
adapterInfo->DeviceName,
adapterInfo->DeviceGuid
));
goto error_exit;
}
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Created interface '%1!ws!' (%2!ws!).\n",
configEntry->InterfaceInfo.Name,
configEntry->InterfaceInfo.Id
));
ClNetDbgPrint((
LOG_NOISE,
"[ClNet] Created network '%1!ws!' (%2!ws!).\n",
configEntry->NetworkInfo.Name,
configEntry->NetworkInfo.Id
));
InsertTailList(
&(ConfigLists->CreatedNetworkList),
&(configEntry->Linkage)
);
//
// Consume the adapter
adapterInfo->Ignore = TRUE;
//
//
// Consume all other adapters that are attached to this
// network
//
ClNetpConsumeAdaptersOnNetwork(
adapterEnum,
adapterIfInfo->NetworkAddressString
);
newNetworkCount++;
}
}
status = ERROR_SUCCESS;
*MatchedNetworkCount = matchedNetworkCount;
*NewNetworkCount = newNetworkCount;
error_exit:
//
// Move unchanged entries back to the input list.
//
while (!IsListEmpty(&unchangedConfigList)) {
listEntry = RemoveHeadList(&(unchangedConfigList));
InsertTailList(&(ConfigLists->InputConfigList), listEntry);
}
//
// Free the adapter resources
//
if (adapterEnum != NULL) {
ClRtlFreeNetAdapterEnum(adapterEnum);
}
if (eventCode != 0) {
wsprintfW(&(errorString[0]), L"%u", status);
(*pClNetLogEvent1)(LOG_CRITICAL, eventCode, errorString);
}
if (status == ERROR_SUCCESS) {
ClNetDbgPrint((LOG_NOISE,
"[ClNet] Network configuration complete...\n"
));
}
return(status);
} // ClNetConfigureNetworks