684 lines
16 KiB
C++
684 lines
16 KiB
C++
//***************************************************************************
|
|
//
|
|
// UPDATECFG.H
|
|
//
|
|
// Module: WMI Framework Instance provider
|
|
//
|
|
// Purpose: Defines class NlbConfigurationUpdate, used for
|
|
// async update of NLB properties associated with a particular NIC.
|
|
//
|
|
// Copyright (c)2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// History:
|
|
//
|
|
// 04/05/01 JosephJ Created
|
|
//
|
|
//***************************************************************************
|
|
|
|
typedef struct _NLB_IP_ADDRESS_INFO NLB_IP_ADDRESS_INFO;
|
|
|
|
//
|
|
// This structure contains all information associated with a particular NIC
|
|
// that is relevant to NLB. This includes the IP addresses bound the NIC,
|
|
// whether or not NLB is bound to the NIC, and if NLB is bound, all
|
|
// the NLB-specific properties.
|
|
//
|
|
class NLB_EXTENDED_CLUSTER_CONFIGURATION
|
|
{
|
|
public:
|
|
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION(VOID) {ZeroMemory(this, sizeof(*this));}
|
|
~NLB_EXTENDED_CLUSTER_CONFIGURATION()
|
|
{
|
|
if (pIpAddressInfo != NULL)
|
|
{
|
|
delete (pIpAddressInfo);
|
|
}
|
|
};
|
|
|
|
WBEMSTATUS
|
|
Update(
|
|
IN const NLB_EXTENDED_CLUSTER_CONFIGURATION *pNewCfg
|
|
);
|
|
|
|
WBEMSTATUS
|
|
SetNetworkAddresses(
|
|
IN LPCWSTR *pszNetworkAddresses,
|
|
IN UINT NumNetworkAddresses
|
|
);
|
|
|
|
WBEMSTATUS
|
|
SetNetworkAddressesSafeArray(
|
|
IN SAFEARRAY *pSA
|
|
);
|
|
|
|
WBEMSTATUS
|
|
GetNetworkAddresses(
|
|
OUT LPWSTR **ppszNetworkAddresses, // free using delete
|
|
OUT UINT *pNumNetworkAddresses
|
|
);
|
|
|
|
WBEMSTATUS
|
|
GetNetworkAddressesSafeArray(
|
|
OUT SAFEARRAY **ppSA
|
|
);
|
|
|
|
WBEMSTATUS
|
|
SetNetworkAddresPairs(
|
|
IN LPCWSTR *pszIpAddresses,
|
|
IN LPCWSTR *pszSubnetMasks,
|
|
IN UINT NumNetworkAddresses
|
|
);
|
|
|
|
WBEMSTATUS
|
|
GetNetworkAddressPairs(
|
|
OUT LPWSTR **ppszIpAddresses, // free using delete
|
|
OUT LPWSTR **ppszIpSubnetMasks, // free using delete
|
|
OUT UINT *pNumNetworkAddresses
|
|
);
|
|
|
|
WBEMSTATUS
|
|
GetPortRules(
|
|
OUT LPWSTR **ppszPortRules,
|
|
OUT UINT *pNumPortRules
|
|
);
|
|
|
|
|
|
WBEMSTATUS
|
|
SetPortRules(
|
|
IN LPCWSTR *pszPortRules,
|
|
IN UINT NumPortRules
|
|
);
|
|
|
|
WBEMSTATUS
|
|
GetPortRulesSafeArray(
|
|
OUT SAFEARRAY **ppSA
|
|
);
|
|
|
|
WBEMSTATUS
|
|
SetPortRulesSafeArray(
|
|
IN SAFEARRAY *pSA
|
|
);
|
|
|
|
UINT GetGeneration(VOID) {return Generation;}
|
|
BOOL IsNlbBound(VOID) {return fBound;}
|
|
BOOL IsValidNlbConfig(VOID) {return fBound && fValidNlbCfg;}
|
|
|
|
WBEMSTATUS
|
|
GetClusterName(
|
|
OUT LPWSTR *pszName
|
|
);
|
|
|
|
VOID
|
|
SetClusterName(
|
|
IN LPCWSTR szName // NULL ok
|
|
);
|
|
|
|
WBEMSTATUS
|
|
GetClusterNetworkAddress(
|
|
OUT LPWSTR *pszAddress
|
|
);
|
|
|
|
VOID
|
|
SetClusterNetworkAddress(
|
|
IN LPCWSTR szAddress // NULL ok
|
|
);
|
|
|
|
WBEMSTATUS
|
|
GetDedicatedNetworkAddress(
|
|
OUT LPWSTR *pszAddress
|
|
);
|
|
|
|
VOID
|
|
SetDedicatedNetworkAddress(
|
|
IN LPCWSTR szAddress // NULL ok
|
|
);
|
|
|
|
typedef enum
|
|
{
|
|
TRAFFIC_MODE_UNICAST,
|
|
TRAFFIC_MODE_MULTICAST,
|
|
TRAFFIC_MODE_IGMPMULTICAST
|
|
|
|
} TRAFFIC_MODE;
|
|
|
|
TRAFFIC_MODE
|
|
GetTrafficMode(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SetTrafficMode(
|
|
TRAFFIC_MODE Mode
|
|
);
|
|
|
|
UINT
|
|
GetHostPriority(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SetHostPriority(
|
|
UINT Priority
|
|
);
|
|
|
|
typedef enum
|
|
{
|
|
START_MODE_STARTED,
|
|
START_MODE_STOPPED
|
|
|
|
} START_MODE;
|
|
|
|
START_MODE
|
|
GetClusterModeOnStart(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SetClusterModeOnStart(
|
|
START_MODE
|
|
);
|
|
|
|
BOOL
|
|
GetRemoteControlEnabled(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SetRemoteControlEnabled(
|
|
BOOL fEnabled
|
|
);
|
|
|
|
//
|
|
// Following fields are public because this class started out as a
|
|
// structure. TODO: wrap these with access methods.
|
|
//
|
|
|
|
BOOL fValidNlbCfg; // True iff all the information is valid.
|
|
UINT Generation; // Generation ID of this Update.
|
|
BOOL fBound; // Whether or not NLB is bound to this NIC.
|
|
BOOL fAddDedicatedIp; // Whether to add the dedicated ip address
|
|
|
|
//
|
|
// When GETTING configuration info, the following provide the full
|
|
// list of statically configured IP addresses on the specified NIC.
|
|
//
|
|
// When SETTING configuration info, the following can either be zero
|
|
// or non-zero. If zero, the set of IP addresses to be added will
|
|
// be inferred from other fields (like cluster vip, per-port vips, etc.)
|
|
// If non-zero, the exact set of VIPS specified will be used.
|
|
//
|
|
UINT NumIpAddresses; // Number of IP addresses bound to the NIC
|
|
NLB_IP_ADDRESS_INFO *pIpAddressInfo; // The actual IP addresses & masks
|
|
|
|
|
|
WLBS_REG_PARAMS NlbParams; // The WLBS-specific configuration
|
|
|
|
};
|
|
|
|
typedef NLB_EXTENDED_CLUSTER_CONFIGURATION *PNLB_EXTENDED_CLUSTER_CONFIGURATION;
|
|
|
|
//
|
|
// The header of a completion header stored as a REG_BINARY value in
|
|
// the registry.
|
|
//
|
|
typedef struct {
|
|
UINT Version;
|
|
UINT Generation; // Redundant, used for internal consistancy check
|
|
UINT CompletionCode;
|
|
UINT Reserved;
|
|
} NLB_COMPLETION_RECORD, *PNLB_COMPLETION_RECORD;
|
|
|
|
#define NLB_CURRENT_COMPLETION_RECORD_VERSION 0x3d7376e2
|
|
|
|
//
|
|
// Prefix of the global event name used to control update access to the specifed
|
|
// NIC.
|
|
// Name has format <prefix><NicGuid>
|
|
// Example event name: NLB_D6901862{EBE09517-07B4-4E88-AAF1-E06F5540608B}
|
|
//
|
|
// The value "D6901862" is a random number.
|
|
//
|
|
#define NLB_CONFIGURATION_EVENT_PREFIX L"NLB_D6901862"
|
|
|
|
//
|
|
// The maximum generation difference between the oldest valid completion
|
|
// record and the current one. Records older then the oldest valid record
|
|
// are subject to pruning.
|
|
//
|
|
#define NLB_MAX_GENERATION_GAP 10
|
|
|
|
class NlbConfigurationUpdate
|
|
{
|
|
public:
|
|
|
|
//
|
|
// Static initialization function -- call in process-attach
|
|
//
|
|
static
|
|
VOID
|
|
Initialize(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Static deinitialization function -- call in process-detach
|
|
//
|
|
static
|
|
VOID
|
|
Deinitialize(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Returns the current configuration on the specific NIC.
|
|
//
|
|
static
|
|
WBEMSTATUS
|
|
GetConfiguration(
|
|
IN LPCWSTR szNicGuid,
|
|
OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCurrentCfg
|
|
);
|
|
|
|
//
|
|
// Called to initiate update to a new cluster state on that NIC. This
|
|
// could include moving from a NLB-bound state to the NLB-unbound state.
|
|
// *pGeneration is used to reference this particular update request.
|
|
//
|
|
static
|
|
WBEMSTATUS
|
|
DoUpdate(
|
|
IN LPCWSTR szNicGuid,
|
|
IN LPCWSTR szClientDescription,
|
|
IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pNewState,
|
|
OUT UINT *pGeneration,
|
|
OUT WCHAR **ppLog // free using delete operator.
|
|
);
|
|
/*++
|
|
ppLog -- will point to a NULL-terminated string which contains
|
|
any messages to be displayed to the user. The string may contain
|
|
embedded (WCHAR) '\n' characters to delimit lines.
|
|
|
|
NOTE: ppLog will be filled out properly EVEN ON FAILURE. If non-null
|
|
it must be deleted by the caller.
|
|
--*/
|
|
|
|
|
|
//
|
|
// Called to get the status of an update request, identified by
|
|
// Generation.
|
|
//
|
|
static
|
|
WBEMSTATUS
|
|
GetUpdateStatus(
|
|
IN LPCWSTR szNicGuid,
|
|
IN UINT Generation,
|
|
IN BOOL fDelete, // Delete record if it exists
|
|
OUT WBEMSTATUS *pCompletionStatus,
|
|
OUT WCHAR **ppLog // free using delete operator.
|
|
);
|
|
|
|
static
|
|
DWORD
|
|
WINAPI
|
|
s_AsyncUpdateThreadProc(
|
|
LPVOID lpParameter // thread data
|
|
);
|
|
|
|
|
|
private:
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// S T A T I C S T U F F
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// A single static lock serialzes all access.
|
|
// Use sfn_Lock and sfn_Unlock.
|
|
//
|
|
static
|
|
CRITICAL_SECTION s_Crit;
|
|
|
|
static
|
|
BOOL
|
|
s_fDeinitializing; // Set to true if we're in the process of
|
|
// de-initializing, in which case we don't want to
|
|
// handle any *new* update requests or even queries.
|
|
|
|
//
|
|
// Global list of current updates, one per NIC.
|
|
//
|
|
static
|
|
LIST_ENTRY
|
|
s_listCurrentUpdates;
|
|
|
|
static
|
|
VOID
|
|
sfn_Lock(
|
|
VOID
|
|
)
|
|
{
|
|
EnterCriticalSection(&s_Crit);
|
|
}
|
|
|
|
static
|
|
VOID
|
|
sfn_Unlock(
|
|
VOID
|
|
)
|
|
{
|
|
LeaveCriticalSection(&s_Crit);
|
|
}
|
|
|
|
//
|
|
// Looks up the current update for the specific NIC.
|
|
// We don't bother to reference count because this object never
|
|
// goes away once created -- it's one per unique NIC GUID for as long as
|
|
// the DLL is loaded (may want to revisit this).
|
|
//
|
|
//
|
|
static
|
|
WBEMSTATUS
|
|
sfn_LookupUpdate(
|
|
IN LPCWSTR szNic,
|
|
IN BOOL fCreate, // Create if required
|
|
OUT NlbConfigurationUpdate ** ppUpdate
|
|
);
|
|
|
|
//
|
|
// Save the specified completion status to the registry.
|
|
//
|
|
static
|
|
WBEMSTATUS
|
|
sfn_RegSetCompletion(
|
|
IN LPCWSTR szNicGuid,
|
|
IN UINT Generation,
|
|
IN WBEMSTATUS CompletionStatus
|
|
);
|
|
|
|
//
|
|
// Retrieve the specified completion status from the registry.
|
|
//
|
|
static
|
|
WBEMSTATUS
|
|
sfn_RegGetCompletion(
|
|
IN LPCWSTR szNicGuid,
|
|
IN UINT Generation,
|
|
OUT WBEMSTATUS *pCompletionStatus,
|
|
OUT WCHAR **ppLog // free using delete operator.
|
|
);
|
|
|
|
//
|
|
// Delete the specified completion status from the registry.
|
|
//
|
|
static
|
|
VOID
|
|
sfn_RegDeleteCompletion(
|
|
IN LPCWSTR szNicGuid,
|
|
IN UINT Generation
|
|
);
|
|
|
|
//
|
|
// Create the specified subkey key (for r/w access) for the specified
|
|
// the specified NIC.
|
|
//
|
|
static
|
|
HKEY
|
|
sfn_RegCreateKey(
|
|
IN LPCWSTR szNicGuid,
|
|
IN LPCWSTR szSubKey,
|
|
IN BOOL fVolatile,
|
|
OUT BOOL *fExists
|
|
);
|
|
|
|
//
|
|
// Open the specified subkey key (for r/w access) for the specified
|
|
// the specified NIC.
|
|
//
|
|
static
|
|
HKEY
|
|
sfn_RegOpenKey(
|
|
IN LPCWSTR szNicGuid,
|
|
IN LPCWSTR szSubKey
|
|
);
|
|
|
|
static
|
|
VOID
|
|
sfn_ReadLog(
|
|
IN HKEY hKeyLog,
|
|
IN UINT Generation,
|
|
OUT LPWSTR *ppLog
|
|
);
|
|
|
|
|
|
static
|
|
VOID
|
|
sfn_WriteLog(
|
|
IN HKEY hKeyLog,
|
|
IN UINT Generation,
|
|
IN LPCWSTR pLog,
|
|
IN BOOL fAppend
|
|
);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// P E R I N S T A N C E S T U F F
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Used in the global one-per-NIC list of updates maintained in
|
|
// s_listCurrentUpdates;
|
|
//
|
|
LIST_ENTRY m_linkUpdates;
|
|
|
|
#define NLB_GUID_LEN 38
|
|
#define NLB_GUID_STRING_SIZE 40 // 38 for the GUID plus trailing NULL + pad
|
|
WCHAR m_szNicGuid[NLB_GUID_STRING_SIZE]; // NIC's GUID in text form
|
|
|
|
LONG m_RefCount;
|
|
|
|
#if OBSOLETE
|
|
//
|
|
// Used by the mfn_Log function;
|
|
//
|
|
struct {
|
|
WCHAR *Start; // Points to first WCHAR in log.
|
|
WCHAR *End; // Points to next place to write.
|
|
UINT_PTR CharsLeft; // WCHARS left in log.
|
|
} m_Log;
|
|
#endif // OBSOLETE
|
|
|
|
typedef enum
|
|
{
|
|
UNITIALIZED, // IDLE -- no ongoing updates
|
|
IDLE, // IDLE -- no ongoing updates
|
|
ACTIVE // There is an ongoing update
|
|
|
|
} MyState;
|
|
|
|
MyState m_State;
|
|
|
|
HANDLE m_hEvent; // Handle to machine-wide update event -- this
|
|
// event is claimed for as long as the current
|
|
// update is ongoing.
|
|
|
|
//
|
|
// The following fields are valid only when the state is ACTIVE
|
|
//
|
|
UINT m_Generation; // Current generation count
|
|
#define NLBUPD_MAX_CLIENT_DESCRIPTION_LENGTH 64
|
|
WCHAR m_szClientDescription[NLBUPD_MAX_CLIENT_DESCRIPTION_LENGTH+1];
|
|
DWORD m_AsyncThreadId; // Thread doing async config update operation.
|
|
HANDLE m_hAsyncThread; // ID of above thread.
|
|
HKEY m_hCompletionKey; // Key to the registry where
|
|
// completions are stored
|
|
|
|
//
|
|
// A snapshot of the cluster configuration state at the start
|
|
// of the update
|
|
//
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION m_OldClusterConfig;
|
|
|
|
//
|
|
// The requested final state
|
|
//
|
|
NLB_EXTENDED_CLUSTER_CONFIGURATION m_NewClusterConfig;
|
|
|
|
|
|
//
|
|
// Completion status of the current update.
|
|
// Could be PENDING.
|
|
//
|
|
WBEMSTATUS m_CompletionStatus;
|
|
|
|
|
|
//
|
|
// END -- of fields that are valid only when the state is ACTIVE
|
|
//
|
|
|
|
|
|
//
|
|
// Constructor and destructor -- note that these are private
|
|
// In fact, the constructor is only called from sfn_LookupUpdate
|
|
// and the destructor from mfn_Dereference.
|
|
//
|
|
NlbConfigurationUpdate(VOID);
|
|
~NlbConfigurationUpdate();
|
|
|
|
//
|
|
// Try to acquire the machine-wide
|
|
// NLB configuration update event for this NIC, and create the
|
|
// appropriate keys in the registry to track this update.
|
|
// NOTE: ppLog will be filled out EVEN ON FAILURE -- it should always
|
|
// be deleted by the caller (using the delete operator) if non-NULL.
|
|
//
|
|
WBEMSTATUS
|
|
mfn_StartUpdate(
|
|
IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pNewState,
|
|
IN LPCWSTR szClientDescription,
|
|
OUT BOOL *pfDoAsync,
|
|
OUT WCHAR ** ppLog
|
|
);
|
|
|
|
//
|
|
// Increment ref count. Object stays alive as long as refcount is nonzero.
|
|
//
|
|
VOID
|
|
mfn_Reference(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Decrement ref count. Object is deleted when refcount goes to zero.
|
|
//
|
|
VOID
|
|
mfn_Dereference(
|
|
VOID
|
|
);
|
|
//
|
|
// Release the machine-wide update event for this NIC, and delete any
|
|
// temporary entries in the registry that were used for this update.
|
|
// ppLog must be deleted by caller useing the delete operator.
|
|
//
|
|
VOID
|
|
mfn_StopUpdate(
|
|
OUT WCHAR ** ppLog
|
|
);
|
|
|
|
//
|
|
// Looks up the completion record identified by Generation, for
|
|
// specific NIC (identified by *this).
|
|
//
|
|
//
|
|
BOOL
|
|
mfn_LookupCompletion(
|
|
IN UINT Generation,
|
|
OUT PNLB_COMPLETION_RECORD *pCompletionRecord
|
|
);
|
|
|
|
//
|
|
// Uses various windows APIs to fill up the current extended cluster
|
|
// information for a specific nic (identified by *this).
|
|
// It fills out pNewCfg.
|
|
// The pNewCfg->field is set to TRUE IFF there were
|
|
// no errors trying to fill out the information.
|
|
//
|
|
//
|
|
WBEMSTATUS
|
|
mfn_GetCurrentClusterConfiguration(
|
|
OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg
|
|
);
|
|
|
|
//
|
|
// Analyzes the nature of the update, mainly to decide whether or not
|
|
// we need to do the update asynchronously.
|
|
// This also performs parameter validation.
|
|
//
|
|
WBEMSTATUS
|
|
mfn_AnalyzeUpdate(
|
|
IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pNewCfg,
|
|
IN BOOL *pDoAsync
|
|
);
|
|
|
|
//
|
|
// Does the update synchronously -- this is where the meat of the update
|
|
// logic exists. It can range from a NoOp, through changing the
|
|
// fields of a single port rule, through binding NLB, setting up cluster
|
|
// parameters and adding the relevant IP addresses in TCPIP.
|
|
//
|
|
VOID
|
|
mfn_ReallyDoUpdate(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
mfn_Log(
|
|
UINT Id, // Resource ID of format,
|
|
...
|
|
);
|
|
|
|
//
|
|
// Following is a shortcut where you directly specify a format string.
|
|
//
|
|
VOID
|
|
mfn_Log(
|
|
LPCWSTR szFormat,
|
|
...
|
|
);
|
|
|
|
VOID
|
|
mfn_LogRawText(
|
|
LPCWSTR szText
|
|
);
|
|
|
|
#if OBSOLETE
|
|
|
|
//
|
|
// Extracts a copy of the current log.
|
|
// The default delete operator should be used to delete *pLog, if NON-NULL.
|
|
//
|
|
VOID
|
|
mfn_ExtractLog(
|
|
OUT LPWSTR *ppLog
|
|
);
|
|
|
|
#endif // OBSOLETE
|
|
|
|
|
|
//
|
|
// Stop the current cluster and take out its vips.
|
|
//
|
|
VOID
|
|
mfn_TakeOutVips(
|
|
VOID
|
|
);
|
|
};
|
|
|
|
VOID
|
|
test_port_rule_string(
|
|
VOID
|
|
);
|