|
|
//***************************************************************************
//
// 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 );
|