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.
 
 
 
 
 
 

2296 lines
59 KiB

//***************************************************************************
//
// EXTCFG.CPP
//
// Module: WMI Framework Instance provider
//
// Purpose: Low-level utilities to configure NICs -- bind/unbind,
// get/set IP address lists, and get/set NLB cluster params.
//
// Copyright (c)2001 Microsoft Corporation, All Rights Reserved
//
// History:
//
// 04/05/01 JosephJ Created (original version, from updatecfg.cpp under
// nlbmgr\provider).
// 07/23/01 JosephJ Moved functionality to lib.
//
//***************************************************************************
#include "private.h"
#include "extcfg.tmh"
//
// NLBUPD_MAX_NETWORK_ADDRESS_LENGTH is the max number of chars (excluding
// the terminating 0) of a string of the form "ip-addr/subnet", eg:
// "10.0.0.1/255.255.255.0"
//
#define NLBUPD_MAX_NETWORK_ADDRESS_LENGTH \
(WLBS_MAX_CL_IP_ADDR + 1 + WLBS_MAX_CL_NET_MASK)
LPWSTR *
allocate_string_array(
UINT NumStrings,
UINT StringLen // excluding ending NULL
);
WBEMSTATUS
address_string_to_ip_and_subnet(
IN LPCWSTR szAddress,
OUT LPWSTR szIp, // max WLBS_MAX_CL_IP_ADDR
OUT LPWSTR szSubnet // max WLBS_MAX_CL_NET_MASK
);
WBEMSTATUS
ip_and_subnet_to_address_string(
IN LPCWSTR szIp,
IN LPCWSTR szSubnet,
IN UINT cchAddress, // length in chars, including NULL.
OUT LPWSTR szAddress // max NLBUPD_MAX_NETWORK_ADDRESS_LENGTH
// + 1 (for NULL)
);
VOID
uint_to_szipaddr(
UINT uIpAddress, // Ip address or subnet -- no validation, network order
UINT cchLen,
WCHAR *rgAddress // Expected to be at least 17 chars long
);
const NLB_IP_ADDRESS_INFO *
find_ip_in_ipinfo(
LPCWSTR szIpToFind,
const NLB_IP_ADDRESS_INFO *pIpInfo,
UINT NumIpInfos
);
NLBERROR
NLB_EXTENDED_CLUSTER_CONFIGURATION::AnalyzeUpdate(
IN OUT NLB_EXTENDED_CLUSTER_CONFIGURATION *pNewCfg,
OUT BOOL *pfConnectivityChange
)
//
// NLBERR_NO_CHANGE -- update is a no-op.
//
// Will MUNGE pNewCfg -- munge NlbParams and also
// fill out pIpAddressInfo if it's NULL.
//
{
NLBERROR nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
BOOL fConnectivityChange = FALSE;
BOOL fSettingsChanged = FALSE;
UINT NumIpAddresses = 0;
NLB_IP_ADDRESS_INFO *pNewIpInfo = NULL;
const NLB_EXTENDED_CLUSTER_CONFIGURATION *pOldCfg = this;
UINT u;
LPCWSTR szFriendlyName = m_szFriendlyName;
if (szFriendlyName == NULL)
{
szFriendlyName = L"";
}
if (pOldCfg->fBound && !pOldCfg->fValidNlbCfg)
{
//
// We're starting with a bound but invalid cluster state -- all bets are
// off.
//
fConnectivityChange = TRUE;
TRACE_CRIT("Analyze: Choosing Async because old state is invalid %ws", szFriendlyName);
}
else if (pOldCfg->fBound != pNewCfg->fBound)
{
//
// bound/unbound state is different -- we do async
//
fConnectivityChange = TRUE;
if (pNewCfg->fBound)
{
TRACE_CRIT("Analyze: Request to bind NLB to %ws", szFriendlyName);
}
else
{
TRACE_CRIT("Analyze: Request to unbind NLB from %ws", szFriendlyName);
}
}
else
{
if (pNewCfg->fBound)
{
TRACE_CRIT("Analyze: Request to change NLB configuration on %ws", szFriendlyName);
}
else
{
TRACE_CRIT("Analyze: NLB not bound and to remain not bound on %ws", szFriendlyName);
}
}
if (pNewCfg->fBound)
{
const WLBS_REG_PARAMS *pOldParams = NULL;
if (pOldCfg->fBound)
{
pOldParams = &pOldCfg->NlbParams;
}
//
// We may have been bound before and we remain bound, let's check if we
// still need to do async, and also vaidate pNewCfg wlbs params in the
// process
//
WBEMSTATUS
TmpStatus = CfgUtilsAnalyzeNlbUpdate(
pOldParams,
&pNewCfg->NlbParams,
&fConnectivityChange
);
if (FAILED(TmpStatus))
{
TRACE_CRIT("Analyze: Error analyzing nlb params for %ws", szFriendlyName);
switch(TmpStatus)
{
case WBEM_E_INVALID_PARAMETER:
nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
break;
case WBEM_E_INITIALIZATION_FAILURE:
nerr = NLBERR_INITIALIZATION_FAILURE;
break;
default:
nerr = NLBERR_LLAPI_FAILURE;
break;
}
goto end;
}
//
// NOTE: CfgUtilsAnalyzeNlbUpdate can return WBEM_S_FALSE if
// the update is a no-op. We should be careful to preserve this
// on success.
//
if (TmpStatus == WBEM_S_FALSE)
{
//
// Let's check if a new password has been specified...
//
if (pNewCfg->NewRemoteControlPasswordSet())
{
fSettingsChanged = TRUE;
}
}
else
{
fSettingsChanged = TRUE;
}
//
// Check the supplied list of IP addresses, to make sure that
// includes the dedicated IP first and the cluster vip and the
// per-port-rule vips.
//
NumIpAddresses = pNewCfg->NumIpAddresses;
if ((NumIpAddresses == 0) != (pNewCfg->pIpAddressInfo == NULL))
{
// Bogus input
TRACE_CRIT("Analze: mismatch between NumIpAddresses and pIpInfo");
goto end;
}
nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
if (NumIpAddresses == 0)
{
BOOL fRet;
NlbIpAddressList IpList;
if (pOldCfg->fBound && pOldCfg->fValidNlbCfg)
{
//
// NLB is currently bound with a valid configuration.
//
//
// If we we're told to do so, we try to preserve
// old IP addresses as far as possible. So we start with the
// old config, remove the old dedicated IP address (if present),
// and primary VIP, and add the new dedicated IP address (if
// present) and cluster vip. If subnet masks have changed for
// these we update them.
//
// All other IP addresses are left intact.
//
//
if (pNewCfg->fAddClusterIps)
{
//
// Start with the original set of ip addresses.
//
fRet = IpList.Set(
pOldCfg->NumIpAddresses,
pOldCfg->pIpAddressInfo,
0
);
if (!fRet)
{
TRACE_CRIT("!FUNC!: IpList.Set (orig ips) failed");
goto end;
}
if (_wcsicmp(pNewCfg->NlbParams.cl_ip_addr,
pOldCfg->NlbParams.cl_ip_addr) )
{
//
// If the cluster IP has changed,
// remove the old cluster IP address.
//
// 1/25/02 josephj NOTE: we only do this
// if the cluster IP has CHANGED,
// otherwise, by taking it out, we lose it's position
// in the old config, so we may end up changing it's
// position unnecessarily (added the wcsicmp
// check above today).
//
// We don't care if it fails.
//
(VOID) IpList.Modify(
pOldCfg->NlbParams.cl_ip_addr,
NULL,
NULL
);
}
//
// Remove the old dedicated IP address first
// We don't care if this fails.
//
(VOID) IpList.Modify(
pOldCfg->NlbParams.ded_ip_addr,
NULL, // new ip address
NULL // new subnet mask
);
}
}
if (pNewCfg->fAddClusterIps)
{
//
// Now add the new cluster Ip address
//
fRet = IpList.Modify(
NULL,
pNewCfg->NlbParams.cl_ip_addr,
pNewCfg->NlbParams.cl_net_mask
);
if (!fRet)
{
TRACE_CRIT("!FUNC!: IpList.Modify (new cl ip) failed");
goto end;
}
}
if (pNewCfg->fAddDedicatedIp)
{
//
// Add the new dedicated IP address --
// to ensure when we add it, it's at the head of the list.
//
//
// We won't add it if it is null, of course.
//
if (!pNewCfg->IsBlankDedicatedIp())
{
fRet = IpList.Modify(
NULL,
pNewCfg->NlbParams.ded_ip_addr,
pNewCfg->NlbParams.ded_net_mask
);
if (!fRet)
{
TRACE_CRIT("!FUNC!: IpList.Modify (new ded ip) failed");
goto end;
}
}
}
//
// Finally, set these new addresses.
//
pNewCfg->SetNetworkAddressesRaw(NULL,0);
IpList.Extract(
REF pNewCfg->NumIpAddresses,
REF pNewCfg->pIpAddressInfo
);
nerr = NLBERR_OK;
} // End case that NumIpAddresses is zero.
//
// We're done munging IP addresses; Now get the latest
// ip address info and count and make sure things look ok.
//
pNewIpInfo = pNewCfg->pIpAddressInfo;
NumIpAddresses = pNewCfg->NumIpAddresses;
nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
//
// Check that dedicated ip address, if present is first.
//
if (pNewCfg->fAddDedicatedIp && !pNewCfg->IsBlankDedicatedIp())
{
if (NumIpAddresses == 0)
{
//
// We don't expect to get here because of checks above, but
// neverthless...
//
TRACE_CRIT("%!FUNC! address list unexpectedly zero");
nerr = NLBERR_INTERNAL_ERROR;
goto end;
}
if (_wcsicmp(pNewIpInfo[0].IpAddress, pNewCfg->NlbParams.ded_ip_addr))
{
TRACE_CRIT("%!FUNC! ERROR: dedicated IP address(%ws) is not first IP address(%ws)",
pNewCfg->NlbParams.ded_ip_addr, pNewIpInfo[0].IpAddress);
goto end;
}
if (_wcsicmp(pNewIpInfo[0].SubnetMask, pNewCfg->NlbParams.ded_net_mask))
{
TRACE_CRIT("%!FUNC! ERROR: dedicated net mask(%ws) does not match IP net mask(%ws)",
pNewCfg->NlbParams.ded_net_mask, pNewIpInfo[0].SubnetMask);
goto end;
}
}
//
// Check that cluster-vip is present
//
if (fAddClusterIps)
{
for (u=0; u< NumIpAddresses; u++)
{
if (!_wcsicmp(pNewIpInfo[u].IpAddress, pNewCfg->NlbParams.cl_ip_addr))
{
//
// Found it! Check that the subnet masks match.
//
if (_wcsicmp(pNewIpInfo[u].SubnetMask, pNewCfg->NlbParams.cl_net_mask))
{
TRACE_CRIT("Cluster subnet mask doesn't match that in addr list");
goto end;
}
break;
}
}
if (u==NumIpAddresses)
{
TRACE_CRIT("Cluster ip address(%ws) is not in the list of addresses!", pNewCfg->NlbParams.cl_ip_addr);
goto end;
}
//
// Check that per-port-rule vips are present.
// TODO
{
}
}
}
else
{
//
// NLB is to be unbound.
//
NumIpAddresses = pNewCfg->NumIpAddresses;
if (NumIpAddresses == 0 && pOldCfg->fBound && pOldCfg->fValidNlbCfg)
{
//
// No ip addresses specified and we're currently bound.
// If the DIP is present in the current
// list of IP addresses, we keep it even after we unbind.
//
const NLB_IP_ADDRESS_INFO *pFoundInfo = NULL;
pFoundInfo = find_ip_in_ipinfo(
pOldCfg->NlbParams.ded_ip_addr,
pOldCfg->pIpAddressInfo,
pOldCfg->NumIpAddresses
);
if (pFoundInfo != NULL)
{
//
// Found it -- let's take it.
//
BOOL fRet;
NlbIpAddressList IpList;
fRet = IpList.Set(1, pFoundInfo, 0);
if (fRet)
{
TRACE_VERB(
"%!FUNC! preserving dedicated ip address %ws on unbind",
pFoundInfo->IpAddress
);
IpList.Extract(
REF pNewCfg->NumIpAddresses,
REF pNewCfg->pIpAddressInfo
);
}
}
}
else
{
//
// We don't do any checking on the supplied
// list of IP addresses -- we assume caller knows best. Note that
// if NULL
// we switch to dhcp/autonet.
//
}
}
nerr = NLBERR_INVALID_CLUSTER_SPECIFICATION;
//
// If there's any change in the list of ipaddresses or subnets, including
// a change in the order, we switch to async.
//
if (pNewCfg->NumIpAddresses != pOldCfg->NumIpAddresses)
{
TRACE_INFO("Analyze: detected change in list of IP addresses on %ws", szFriendlyName);
fConnectivityChange = TRUE;
}
else
{
NLB_IP_ADDRESS_INFO *pOldIpInfo = NULL;
//
// Check if there is a change in the list of ip addresses or
// their order of appearance.
//
NumIpAddresses = pNewCfg->NumIpAddresses;
pOldIpInfo = pOldCfg->pIpAddressInfo;
pNewIpInfo = pNewCfg->pIpAddressInfo;
for (u=0; u<NumIpAddresses; u++)
{
if ( _wcsicmp(pNewIpInfo[u].IpAddress, pOldIpInfo[u].IpAddress)
|| _wcsicmp(pNewIpInfo[u].SubnetMask, pOldIpInfo[u].SubnetMask))
{
TRACE_INFO("Analyze: detected change in list of IP addresses on %ws", szFriendlyName);
fConnectivityChange = TRUE;
break;
}
}
}
nerr = NLBERR_OK;
end:
if (nerr == NLBERR_OK)
{
*pfConnectivityChange = fConnectivityChange;
if (fConnectivityChange)
{
fSettingsChanged = TRUE;
}
if (fSettingsChanged)
{
nerr = NLBERR_OK;
}
else
{
nerr = NLBERR_NO_CHANGE;
}
}
return nerr;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::Update(
IN const NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfgNew
)
//
// Applies the properties in pCfgNew to this.
// Does NOT copy szNewRemoteControlPassword -- instead sets that field to NULL
//
{
WBEMSTATUS Status;
UINT NumIpAddresses = pCfgNew->NumIpAddresses;
NLB_IP_ADDRESS_INFO *pIpAddressInfo = NULL;
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg = this;
//
// Free and realloc pCfg's ip info array if rquired.
//
if (pCfg->NumIpAddresses == NumIpAddresses)
{
//
// we can re-use the existing one
//
pIpAddressInfo = pCfg->pIpAddressInfo;
}
else
{
//
// Free the old one and allocate space for the new array if required.
//
if (NumIpAddresses != 0)
{
pIpAddressInfo = new NLB_IP_ADDRESS_INFO[NumIpAddresses];
if (pIpAddressInfo == NULL)
{
TRACE_CRIT(L"Error allocating space for IP address info array");
Status = WBEM_E_OUT_OF_MEMORY;
goto end;
}
}
if (pCfg->NumIpAddresses!=0)
{
delete pCfg->pIpAddressInfo;
pCfg->pIpAddressInfo = NULL;
pCfg->NumIpAddresses = 0;
}
}
//
// Copy over the new ip address info, if there is any.
//
if (NumIpAddresses)
{
CopyMemory(
pIpAddressInfo,
pCfgNew->pIpAddressInfo,
NumIpAddresses*sizeof(*pIpAddressInfo)
);
}
//
// Do any other error checks here.
//
//
// Struct copy the entire structure, then fix up the pointer to
// ip address info array.
//
(VOID) pCfg->SetFriendlyName(NULL);
delete m_szNewRemoteControlPassword;
*pCfg = *pCfgNew; // struct copy
pCfg->m_szFriendlyName = NULL; // TODO: clean this up.
pCfg->m_szNewRemoteControlPassword = NULL;
pCfg->pIpAddressInfo = pIpAddressInfo;
pCfg->NumIpAddresses = NumIpAddresses;
(VOID) pCfg->SetFriendlyName(pCfgNew->m_szFriendlyName);
//
// Update does NOT copy over the new remote control password or
// new hashed password -- in fact
// it ends up clearing the new password fields.
//
pCfg->ClearNewRemoteControlPassword();
Status = WBEM_NO_ERROR;
end:
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetNetworkAddresses(
IN LPCWSTR *pszNetworkAddresses,
IN UINT NumNetworkAddresses
)
/*
pszNetworkAddresses is an array of strings. These strings have the
format "addr/subnet", eg: "10.0.0.1/255.0.0.0"
*/
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
if (NumNetworkAddresses != 0)
{
UINT NumBad = 0;
//
// Allocate space for the new ip-address-info array
//
pIpInfo = new NLB_IP_ADDRESS_INFO[NumNetworkAddresses];
if (pIpInfo == NULL)
{
TRACE_CRIT("%!FUNC!: Alloc failure!");
Status = WBEM_E_OUT_OF_MEMORY;
goto end;
}
ZeroMemory(pIpInfo, NumNetworkAddresses*sizeof(*pIpInfo));
//
// Convert IP addresses to our internal form.
//
for (UINT u=0;u<NumNetworkAddresses; u++)
{
//
// We extrace each IP address and it's corresponding subnet mask
// from the "addr/subnet" format insert it into a
// NLB_IP_ADDRESS_INFO structure.
//
// SAMPLE: 10.0.0.1/255.0.0.0
//
LPCWSTR szAddr = pszNetworkAddresses[u];
UINT uIpAddress = 0;
//
// If this is not a valid address, we skip it.
//
Status = CfgUtilsValidateNetworkAddress(
szAddr,
&uIpAddress,
NULL,
NULL
);
if (FAILED(Status))
{
TRACE_CRIT("%!FUNC!: Invalid ip or subnet: %ws", szAddr);
NumBad++;
continue;
}
ASSERT(u>=NumBad);
Status = address_string_to_ip_and_subnet(
szAddr,
pIpInfo[u-NumBad].IpAddress,
pIpInfo[u-NumBad].SubnetMask
);
if (FAILED(Status))
{
//
// This one of the ip/subnet parms is too large.
//
TRACE_CRIT("%!FUNC!:ip or subnet part too large: %ws", szAddr);
goto end;
}
}
NumNetworkAddresses -= NumBad;
if (NumNetworkAddresses == 0)
{
delete[] pIpInfo;
pIpInfo = NULL;
}
}
//
// Replace the old ip-address-info with the new one
//
if (this->pIpAddressInfo != NULL)
{
delete this->pIpAddressInfo;
this->pIpAddressInfo = NULL;
}
this->pIpAddressInfo = pIpInfo;
pIpInfo = NULL;
this->NumIpAddresses = NumNetworkAddresses;
Status = WBEM_NO_ERROR;
end:
if (pIpInfo != NULL)
{
delete[] pIpInfo;
}
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetNetworkAddresses(
OUT LPWSTR **ppszNetworkAddresses, // free using delete
OUT UINT *pNumNetworkAddresses
)
/*
ppszNetworkAddresses is filled out on successful return to
an array of strings. These strings have the
format "addr/subnet", eg: "10.0.0.1/255.0.0.0"
*/
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
UINT AddrCount = this->NumIpAddresses;
NLB_IP_ADDRESS_INFO *pIpInfo = this->pIpAddressInfo;
LPWSTR *pszNetworkAddresses = NULL;
if (AddrCount != 0)
{
//
// Convert IP addresses from our internal form into
// format "addr/subnet", eg: "10.0.0.1/255.0.0.0"
//
//
const UINT cchLen = WLBS_MAX_CL_IP_ADDR // for IP address
+ WLBS_MAX_CL_NET_MASK // for subnet mask
+ 1; // for separating '/'
pszNetworkAddresses = allocate_string_array(
AddrCount,
cchLen
);
if (pszNetworkAddresses == NULL)
{
TRACE_CRIT("%!FUNC!: Alloc failure!");
Status = WBEM_E_OUT_OF_MEMORY;
goto end;
}
for (UINT u=0;u<AddrCount; u++)
{
//
// We extrace each IP address and it's corresponding subnet mask
// insert them into a NLB_IP_ADDRESS_INFO
// structure.
//
LPCWSTR pIpSrc = pIpInfo[u].IpAddress;
LPCWSTR pSubSrc = pIpInfo[u].SubnetMask;
LPWSTR szDest = pszNetworkAddresses[u];
Status = ip_and_subnet_to_address_string(
pIpSrc,
pSubSrc,
cchLen,
szDest
);
if (FAILED(Status))
{
//
// This would be an implementation error in get_multi_string_...
//
ASSERT(FALSE);
Status = WBEM_E_CRITICAL_ERROR;
goto end;
}
}
}
Status = WBEM_NO_ERROR;
end:
if (FAILED(Status))
{
if (pszNetworkAddresses != NULL)
{
delete pszNetworkAddresses;
pszNetworkAddresses = NULL;
}
AddrCount = 0;
}
*ppszNetworkAddresses = pszNetworkAddresses;
*pNumNetworkAddresses = AddrCount;
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetNetworkAddresPairs(
IN LPCWSTR *pszIpAddresses,
IN LPCWSTR *pszSubnetMasks,
IN UINT NumNetworkAddresses
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
goto end;
end:
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetNetworkAddressPairs(
OUT LPWSTR **ppszIpAddresses, // free using delete
OUT LPWSTR **ppszIpSubnetMasks, // free using delete
OUT UINT *pNumNetworkAddresses
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
goto end;
end:
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetPortRules(
OUT LPWSTR **ppszPortRules,
OUT UINT *pNumPortRules
)
{
WLBS_PORT_RULE *pRules = NULL;
UINT NumRules = 0;
WBEMSTATUS Status;
LPWSTR *pszPortRules = NULL;
// DebugBreak();
*ppszPortRules = NULL;
*pNumPortRules = 0;
Status = CfgUtilGetPortRules(
&NlbParams,
&pRules,
&NumRules
);
if (FAILED(Status) || NumRules == 0)
{
pRules = NULL;
goto end;
}
pszPortRules = CfgUtilsAllocateStringArray(
NumRules,
NLB_MAX_PORT_STRING_SIZE
);
if (pszPortRules == NULL)
{
Status = WBEM_E_OUT_OF_MEMORY;
goto end;
}
//
// Now convert from the binary to the string format.
//
for (UINT u = 0; u< NumRules; u++)
{
BOOL fRet;
fRet = CfgUtilsGetPortRuleString(
pRules+u,
pszPortRules[u]
);
if (!fRet)
{
//
// Must be a bad binary port rule!
// For now, we just set the port rule to "".
//
*pszPortRules[u]=0;
TRACE_INFO("%!FUNC!: Invalid port rule %lu", u);
}
}
Status = WBEM_NO_ERROR;
end:
delete pRules;
*pNumPortRules = NumRules;
*ppszPortRules = pszPortRules;
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetPortRules(
IN LPCWSTR *pszPortRules,
IN UINT NumPortRules
)
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
WLBS_PORT_RULE *pRules = NULL;
// DebugBreak();
if (NumPortRules!=0)
{
pRules = new WLBS_PORT_RULE[NumPortRules];
if (pRules == NULL)
{
TRACE_CRIT("%!FUNC!: Allocation failure!");
Status = WBEM_E_OUT_OF_MEMORY;
goto end;
}
}
//
// Initialiez the binary form of the port rules.
//
for (UINT u=0; u < NumPortRules; u++)
{
LPCWSTR szRule = pszPortRules[u];
BOOL fRet;
fRet = CfgUtilsSetPortRuleString(
szRule,
pRules+u
);
if (fRet == FALSE)
{
Status = WBEM_E_INVALID_PARAMETER;
goto end;
}
}
Status = CfgUtilSetPortRules(
pRules,
NumPortRules,
&NlbParams
);
end:
delete[] pRules;
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetPortRulesSafeArray(
IN SAFEARRAY *pSA
)
{
return WBEM_E_CRITICAL_ERROR;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetPortRulesSafeArray(
OUT SAFEARRAY **ppSA
)
{
return WBEM_E_CRITICAL_ERROR;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetClusterNetworkAddress(
OUT LPWSTR *pszAddress
)
/*
allocate and return the cluster-ip and mask in address/subnet form.
Eg: "10.0.0.1/255.0.0.0"
*/
{
WBEMSTATUS Status = WBEM_E_OUT_OF_MEMORY;
LPWSTR szAddress = NULL;
if (fValidNlbCfg)
{
szAddress = new WCHAR[NLBUPD_MAX_NETWORK_ADDRESS_LENGTH+1];
if (szAddress != NULL)
{
Status = ip_and_subnet_to_address_string(
NlbParams.cl_ip_addr,
NlbParams.cl_net_mask,
NLBUPD_MAX_NETWORK_ADDRESS_LENGTH+1,
szAddress
);
if (FAILED(Status))
{
delete[] szAddress;
szAddress = NULL;
}
}
}
*pszAddress = szAddress;
return Status;
}
VOID
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetClusterNetworkAddress(
IN LPCWSTR szAddress
)
{
if (szAddress == NULL) szAddress = L"";
(VOID) address_string_to_ip_and_subnet(
szAddress,
NlbParams.cl_ip_addr,
NlbParams.cl_net_mask
);
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetClusterName(
OUT LPWSTR *pszName
)
/*
allocate and return the cluster name
*/
{
WBEMSTATUS Status = WBEM_E_OUT_OF_MEMORY;
LPWSTR szName = NULL;
if (fValidNlbCfg)
{
UINT len = wcslen(NlbParams.domain_name);
szName = new WCHAR[len+1]; // +1 for ending zero
if (szName != NULL)
{
CopyMemory(szName, NlbParams.domain_name, (len+1)*sizeof(WCHAR));
Status = WBEM_NO_ERROR;
}
}
*pszName = szName;
return Status;
}
VOID
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetClusterName(
IN LPCWSTR szName
)
{
if (szName == NULL) szName = L"";
UINT len = wcslen(szName);
if (len>WLBS_MAX_DOMAIN_NAME)
{
TRACE_CRIT("%!FUNC!: Cluster name too large");
}
CopyMemory(NlbParams.domain_name, szName, (len+1)*sizeof(WCHAR));
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetDedicatedNetworkAddress(
OUT LPWSTR *pszAddress
)
{
WBEMSTATUS Status = WBEM_E_OUT_OF_MEMORY;
LPWSTR szAddress = NULL;
if (fValidNlbCfg)
{
szAddress = new WCHAR[NLBUPD_MAX_NETWORK_ADDRESS_LENGTH+1];
if (szAddress != NULL)
{
Status = ip_and_subnet_to_address_string(
NlbParams.ded_ip_addr,
NlbParams.ded_net_mask,
NLBUPD_MAX_NETWORK_ADDRESS_LENGTH+1,
szAddress
);
if (FAILED(Status))
{
delete[] szAddress;
szAddress = NULL;
}
}
}
*pszAddress = szAddress;
return Status;
}
VOID
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetDedicatedNetworkAddress(
IN LPCWSTR szAddress
)
{
if (szAddress == NULL || *szAddress == 0)
{
ARRAYSTRCPY(NlbParams.ded_ip_addr, CVY_DEF_DED_IP_ADDR);
ARRAYSTRCPY(NlbParams.ded_net_mask, CVY_DEF_DED_NET_MASK);
}
else
{
(VOID) address_string_to_ip_and_subnet(
szAddress,
NlbParams.ded_ip_addr,
NlbParams.ded_net_mask
);
}
}
NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetTrafficMode(
VOID
) const
{
TRAFFIC_MODE TrafficMode = TRAFFIC_MODE_UNICAST;
if (NlbParams.mcast_support)
{
if (NlbParams.fIGMPSupport)
{
TrafficMode = TRAFFIC_MODE_IGMPMULTICAST;
}
else
{
TrafficMode = TRAFFIC_MODE_MULTICAST;
}
}
return TrafficMode;
}
VOID
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetTrafficMode(
TRAFFIC_MODE Mode
)
{
switch(Mode)
{
case TRAFFIC_MODE_UNICAST:
NlbParams.mcast_support = 0;
NlbParams.fIGMPSupport = 0;
break;
case TRAFFIC_MODE_IGMPMULTICAST:
NlbParams.mcast_support = 1;
NlbParams.fIGMPSupport = 1;
break;
case TRAFFIC_MODE_MULTICAST:
NlbParams.mcast_support = 1;
NlbParams.fIGMPSupport = 0;
break;
default:
ASSERT(FALSE);
break;
}
}
UINT
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetHostPriority(
VOID
)
{
return NlbParams.host_priority;
}
VOID
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetHostPriority(
UINT Priority
)
{
NlbParams.host_priority = Priority;
}
//NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE
DWORD
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetClusterModeOnStart(
VOID
)
{
//
// If we decide to make cluster_mode something besides true/false we
// need to make the change here too...
//
/*
ASSERT(NlbParams.cluster_mode==TRUE || NlbParams.cluster_mode==FALSE);
if (NlbParams.cluster_mode)
{
return START_MODE_STARTED;
}
else
{
return START_MODE_STOPPED;
}
*/
return NlbParams.cluster_mode;
}
VOID
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetClusterModeOnStart(
// START_MODE Mode
DWORD Mode
)
{
/*
switch(Mode)
{
case START_MODE_STARTED:
NlbParams.cluster_mode = TRUE;
break;
case START_MODE_STOPPED:
NlbParams.cluster_mode = FALSE;
break;
default:
ASSERT(FALSE);
break;
}
*/
NlbParams.cluster_mode = Mode;
}
BOOL
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetPersistSuspendOnReboot(
VOID
)
{
// This is a straight lift from wmi\ClusterWrapper.cpp\GetNodeConfig()
// -KarthicN
return ((NlbParams.persisted_states & CVY_PERSIST_STATE_SUSPENDED) != 0);
}
VOID
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetPersistSuspendOnReboot(
BOOL bPersistSuspendOnReboot
)
{
// This is a straight lift from wmi\ClusterWrapper.cpp\PutNodeConfig()
// -KarthicN
if (bPersistSuspendOnReboot)
{
NlbParams.persisted_states |= CVY_PERSIST_STATE_SUSPENDED;
}
else
{
NlbParams.persisted_states &= ~CVY_PERSIST_STATE_SUSPENDED;
}
}
BOOL
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetRemoteControlEnabled(
VOID
) const
{
return (NlbParams.rct_enabled!=FALSE);
}
VOID
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetRemoteControlEnabled(
BOOL fEnabled
)
{
NlbParams.rct_enabled = (fEnabled!=FALSE);
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetNetworkAddressesSafeArray(
IN SAFEARRAY *pSA
)
{
LPWSTR *pStrings=NULL;
UINT NumStrings = 0;
WBEMSTATUS Status;
Status = CfgUtilStringsFromSafeArray(
pSA,
&pStrings, // delete when done useing pStrings
&NumStrings
);
if (FAILED(Status))
{
pStrings=NULL;
goto end;
}
Status = this->SetNetworkAddresses(
(LPCWSTR*)pStrings,
NumStrings
);
if (pStrings != NULL)
{
delete pStrings;
}
end:
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetNetworkAddressesSafeArray(
OUT SAFEARRAY **ppSA
)
{
LPWSTR *pszNetworkAddresses = NULL;
UINT NumNetworkAddresses = 0;
SAFEARRAY *pSA=NULL;
WBEMSTATUS Status;
Status = this->GetNetworkAddresses(
&pszNetworkAddresses,
&NumNetworkAddresses
);
if (FAILED(Status))
{
pszNetworkAddresses = NULL;
goto end;
}
Status = CfgUtilSafeArrayFromStrings(
(LPCWSTR*) pszNetworkAddresses,
NumNetworkAddresses, // can be zero
&pSA
);
if (FAILED(Status))
{
pSA = NULL;
}
end:
*ppSA = pSA;
if (pszNetworkAddresses != NULL)
{
delete pszNetworkAddresses;
pszNetworkAddresses = NULL;
}
if (FAILED(Status))
{
TRACE_CRIT("%!FUNC!: couldn't extract network addresses from Cfg");
}
return Status;
}
LPWSTR *
allocate_string_array(
UINT NumStrings,
UINT MaxStringLen // excluding ending NULL
)
/*
Allocate a single chunk of memory using the new LPWSTR[] operator.
The first NumStrings LPWSTR values of this operator contain an array
of pointers to WCHAR strings. Each of these strings
is of size (MaxStringLen+1) WCHARS.
The rest of the memory contains the strings themselve.
Return NULL if NumStrings==0 or on allocation failure.
Each of the strings are initialized to be empty strings (first char is 0).
*/
{
return CfgUtilsAllocateStringArray(NumStrings, MaxStringLen);
}
WBEMSTATUS
address_string_to_ip_and_subnet(
IN LPCWSTR szAddress,
OUT LPWSTR szIp, // max WLBS_MAX_CL_IP_ADDR including NULL
OUT LPWSTR szSubnet // max WLBS_MAX_CL_NET_MASK including NULL
)
// Special case: if szAddress == "", we zero out both szIp and szSubnet;
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
if (*szAddress == 0) {szAddress = L"/";} // Special case mentioned above
// from the "addr/subnet" format insert it into a
// NLB_IP_ADDRESS_INFO structure.
//
// SAMPLE: 10.0.0.1/255.0.0.0
//
LPCWSTR pSlash = NULL;
LPCWSTR pSrcSub = NULL;
*szIp = 0;
*szSubnet = 0;
pSlash = wcsrchr(szAddress, (int) '/');
if (pSlash == NULL)
{
TRACE_CRIT("%!FUNC!:missing subnet portion in %ws", szAddress);
Status = WBEM_E_INVALID_PARAMETER;
goto end;
}
pSrcSub = pSlash+1;
UINT len = (UINT) (pSlash - szAddress);
UINT len1 = wcslen(pSrcSub);
if ( (len < WLBS_MAX_CL_IP_ADDR) && (len1 < WLBS_MAX_CL_NET_MASK))
{
CopyMemory(szIp, szAddress, len*sizeof(WCHAR));
szIp[len] = 0;
CopyMemory(szSubnet, pSrcSub, (len1+1)*sizeof(WCHAR));
}
else
{
//
// One of the ip/subnet parms is too large.
//
TRACE_CRIT("%!FUNC!:ip or subnet part too large: %ws", szAddress);
Status = WBEM_E_INVALID_PARAMETER;
goto end;
}
Status = WBEM_NO_ERROR;
end:
return Status;
}
WBEMSTATUS
ip_and_subnet_to_address_string(
IN LPCWSTR szIp,
IN LPCWSTR szSubnet,
IN UINT cchAddress,
OUT LPWSTR szAddress// max WLBS_MAX_CL_IP_ADDR
// + 1(for slash) + WLBS_MAX_CL_NET_MASK + 1 (for NULL)
)
{
WBEMSTATUS Status = WBEM_E_INVALID_PARAMETER;
UINT len = wcslen(szIp)+wcslen(szSubnet) + 1; // +1 for separating '/'
if (len >= NLBUPD_MAX_NETWORK_ADDRESS_LENGTH)
{
goto end;
}
else
{
HRESULT hr;
hr = StringCchPrintf(
szAddress,
cchAddress,
L"%ws/%ws",
szIp,
szSubnet
);
if (hr == S_OK)
{
Status = WBEM_NO_ERROR;
}
else
{
Status = WBEM_E_INVALID_PARAMETER;
}
}
end:
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::GetFriendlyName(
OUT LPWSTR *pszFriendlyName // Free using delete
) const
{
WBEMSTATUS Status = WBEM_E_NOT_FOUND;
LPWSTR szName = NULL;
*pszFriendlyName = NULL;
if (m_szFriendlyName != NULL)
{
UINT len = wcslen(m_szFriendlyName);
szName = new WCHAR[len+1]; // +1 for ending 0
if (szName == NULL)
{
Status = WBEM_E_OUT_OF_MEMORY;
}
else
{
Status = WBEM_NO_ERROR;
CopyMemory(szName, m_szFriendlyName, (len+1)*sizeof(WCHAR));
}
}
*pszFriendlyName = szName;
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetFriendlyName(
IN LPCWSTR szFriendlyName // Saves a copy of szFriendlyName
)
{
WBEMSTATUS Status = WBEM_E_OUT_OF_MEMORY;
LPWSTR szName = NULL;
if (szFriendlyName != NULL)
{
UINT len = wcslen(szFriendlyName);
szName = new WCHAR[len+1]; // +1 for ending 0
if (szName == NULL)
{
goto end;
}
else
{
CopyMemory(szName, szFriendlyName, (len+1)*sizeof(WCHAR));
}
}
Status = WBEM_NO_ERROR;
if (m_szFriendlyName != NULL)
{
delete m_szFriendlyName;
m_szFriendlyName = NULL;
}
m_szFriendlyName = szName;
end:
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::SetNewRemoteControlPassword(
IN LPCWSTR szRemoteControlPassword // Saves a copy of szRemoteControlPassword
)
{
WBEMSTATUS Status = WBEM_E_OUT_OF_MEMORY;
LPWSTR szName = NULL;
if (szRemoteControlPassword != NULL)
{
UINT len = wcslen(szRemoteControlPassword);
szName = new WCHAR[len+1]; // +1 for ending 0
if (szName == NULL)
{
goto end;
}
else
{
CopyMemory(szName, szRemoteControlPassword, (len+1)*sizeof(WCHAR));
}
m_fSetPassword = TRUE;
}
else
{
m_fSetPassword = FALSE;
}
Status = WBEM_NO_ERROR;
if (m_szNewRemoteControlPassword != NULL)
{
delete m_szNewRemoteControlPassword;
m_szNewRemoteControlPassword = NULL;
}
m_szNewRemoteControlPassword = szName;
end:
return Status;
}
WBEMSTATUS
NLB_EXTENDED_CLUSTER_CONFIGURATION::
ModifyNetworkAddress(
IN LPCWSTR szOldIpAddress, OPTIONAL // network order
IN LPCWSTR szNewIpAddress, OPTIONAL
IN LPCWSTR szNewSubnetMask OPTIONAL
)
//
// NULL, NULL: clear all network addresses
// NULL, szNew: add
// szOld, NULL: remove
// szOld, szNew: replace (or add, if old doesn't exist)
//
{
WBEMSTATUS Status = WBEM_E_INVALID_PARAMETER;
BOOL fRet;
NlbIpAddressList IpList;
fRet = IpList.Set(this->NumIpAddresses, this->pIpAddressInfo, 0);
if (fRet)
{
fRet = IpList.Modify(
szOldIpAddress,
szNewIpAddress,
szNewSubnetMask
);
}
if (fRet)
{
this->SetNetworkAddressesRaw(NULL,0);
IpList.Extract(REF this->NumIpAddresses, REF this->pIpAddressInfo);
Status = WBEM_NO_ERROR;
}
else
{
Status = WBEM_E_INVALID_PARAMETER;
}
return Status;
}
BOOL
NLB_EXTENDED_CLUSTER_CONFIGURATION::
IsBlankDedicatedIp(
VOID
) const
//
// Dedicated IP is either the empty string or all zeros.
//
{
return (NlbParams.ded_ip_addr[0]==0)
|| (_wcsspnp(NlbParams.ded_ip_addr, L".0")==NULL);
}
const NLB_IP_ADDRESS_INFO *
NlbIpAddressList::Find(
LPCWSTR szIp // IF NULL, returns first address
) const
//
// Looks for the specified IP address -- returns an internal pointer
// to the found IP address info, if fount, otherwise NULL.
//
{
const NLB_IP_ADDRESS_INFO *pInfo = NULL;
if (szIp == NULL)
{
//
// return the first if there is one, else NULL.
//
if (m_uNum != 0)
{
pInfo = m_pIpInfo;
}
}
else
{
pInfo = find_ip_in_ipinfo(szIp, m_pIpInfo, m_uNum);
}
return pInfo;
}
BOOL
NlbIpAddressList::Copy(const NlbIpAddressList &refList)
{
BOOL fRet;
fRet = this->Set(refList.m_uNum, refList.m_pIpInfo, 0);
return fRet;
}
BOOL
NlbIpAddressList::Validate(void)
// checks that there are no dups and all valid ip/subnets
{
BOOL fRet = FALSE;
NLB_IP_ADDRESS_INFO *pInfo = m_pIpInfo;
UINT uNum = m_uNum;
for (UINT u = 0; u<uNum; u++)
{
UINT uIpAddress = 0;
fRet = sfn_validate_info(REF pInfo[u], REF uIpAddress);
if (!fRet) break;
}
return fRet;
}
BOOL
NlbIpAddressList::Set(
UINT uNew,
const NLB_IP_ADDRESS_INFO *pNewInfo,
UINT uExtraCount
)
/*
Sets internal list to a copy of pNewInfo. Reallocates list if required.
Reserves uExtraCount empty locations (perhaps more if it kept the old
internal list)
*/
{
BOOL fRet = FALSE;
UINT uMax = uNew+uExtraCount;
NLB_IP_ADDRESS_INFO *pInfo = NULL;
// printf("-> set(%lu, %p, %lu): m_uNum=%lu m_uMax=%lu m_pIpInfo=0x%p\n",
// uNew, pNewInfo, uExtraCount,
// m_uNum, m_uMax, m_pIpInfo);
if (uMax > m_uMax)
{
//
// We'll re-allocate to get more space.
//
pInfo = new NLB_IP_ADDRESS_INFO[uMax];
if (pInfo == NULL)
{
TRACE_CRIT("%!FUNC! allocation failure");
goto end;
}
}
else
{
//
// The current m_pIpInfo is large enough; we'll keep it.
//
pInfo = m_pIpInfo;
uMax = m_uMax;
}
if (uNew != 0)
{
if (pNewInfo == pInfo)
{
// Caller has passed m_pInfo as pNewInfo.
// No need to copy.
}
else
{
//
// MoveMemory can deal with overlapping regions.
//
MoveMemory(pInfo, pNewInfo, sizeof(NLB_IP_ADDRESS_INFO)*uNew);
}
}
if (uMax > uNew)
{
//
// Zero out the empty space.
//
ZeroMemory(pInfo+uNew, sizeof(NLB_IP_ADDRESS_INFO)*(uMax-uNew));
}
m_uNum = uNew;
m_uMax = uMax;
if (m_pIpInfo != pInfo)
{
delete[] m_pIpInfo;
m_pIpInfo = pInfo;
}
fRet = TRUE;
end:
// printf("<- set: fRet=%lu, m_uNum=%lu m_uMax=%lu m_pIpInfo=0x%p\n",
// fRet, m_uNum, m_uMax, m_pIpInfo);
return fRet;
}
VOID
NlbIpAddressList::Extract(UINT &uNum, NLB_IP_ADDRESS_INFO * &pNewInfo)
/*
Sets pNewInfo to the ip list (not a copy) and sets the internal list to
null. Free using delete[].
*/
{
uNum = m_uNum;
pNewInfo = m_pIpInfo;
m_uNum=0;
m_uMax=0;
m_pIpInfo = NULL;
}
static
VOID
uint_to_szipaddr(
UINT uIpAddress, // Ip address or subnet -- no validation, network order
UINT cchLen, // length of rgAddress, incluing space for NULL
WCHAR *rgAddress // Expected to be at least 17 chars long
)
{
BYTE *pb = (BYTE*) &uIpAddress;
StringCchPrintf(rgAddress, cchLen, L"%lu.%lu.%lu.%lu", pb[0], pb[1], pb[2], pb[3]);
}
BOOL
NlbIpAddressList::Modify(
LPCWSTR szOldIp,
LPCWSTR szNewIp,
LPCWSTR szNewSubnet
)
//
// NULL, NULL, -: clear all network addresses
// NULL, szNew, -: add
// szOld, NULL, -: remove
// szOld, szNew, -: remove szOld if found; add or replace szNew.
//
{
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
BOOL fRet = FALSE;
UINT uFoundOldOffset = 0;
BOOL fFoundOldAddress = FALSE;
// printf("-> modify: m_uNum=%lu m_uMax=%lu m_pIpInfo=0x%p\n",
// m_uNum, m_uMax, m_pIpInfo);
if (szOldIp==NULL && szNewIp==NULL)
{
this->Clear();
fRet = TRUE;
goto end;
}
if (szOldIp != NULL && szNewIp != NULL)
{
//
// Both szOld and szNew are specified.
// We'll first call ourselves recursively to remove szNewIp, if
// it exists. Later on below we'll replace szOldIp with szNewIp
// if szOldIp exists (i.e. at the same LOCATION of szOldIp), or
// add it to the beginning if szOldIp doesn't exist.
//
(void) this->Modify(szNewIp, NULL, NULL);
}
if (szOldIp == NULL)
{
szOldIp = szNewIp; // so we don't add dups.
}
if (szOldIp != NULL)
{
const NLB_IP_ADDRESS_INFO *pFoundInfo = NULL;
pFoundInfo = find_ip_in_ipinfo(szOldIp, m_pIpInfo, m_uNum);
if(pFoundInfo != NULL)
{
uFoundOldOffset = (ULONG) (UINT_PTR) (pFoundInfo-m_pIpInfo);
fFoundOldAddress = TRUE;
}
}
if (szNewIp == NULL)
{
//
// Remove old Ip address
//
if (!fFoundOldAddress)
{
//
// Old one not found
//
fRet = FALSE;
goto end;
}
//
// We bump up everything beyond this one
//
m_uNum--; // that this was at least 1 because we found the old
for (UINT u=uFoundOldOffset; u<m_uNum; u++)
{
m_pIpInfo[u] = m_pIpInfo[u+1]; // struct copy.
}
//
// Zero out the last (vacated) element.
//
ZeroMemory(&m_pIpInfo[m_uNum], sizeof(*m_pIpInfo));
}
else
{
UINT uNewIpAddress=0;
UINT uNewSubnetMask=0;
NLB_IP_ADDRESS_INFO NewIpInfo;
ZeroMemory(&NewIpInfo, sizeof(NewIpInfo));
Status = CfgUtilsValidateNetworkAddress(
szNewIp,
&uNewIpAddress,
NULL,
NULL
);
if (!FAILED(Status))
{
Status = CfgUtilsValidateNetworkAddress(
szNewSubnet,
&uNewSubnetMask,
NULL,
NULL
);
}
if (FAILED(Status))
{
//
// Invalid ip address.
//
TRACE_CRIT("%!FUNC!:ip or subnet part too large: %ws/%ws",
szNewIp, szNewSubnet);
fRet = FALSE;
goto end;
}
//
// Convert into the IP_ADDRESS_INFO format.
// Here we also convert to standard dotted notation.
//
uint_to_szipaddr(uNewIpAddress, ASIZE(NewIpInfo.IpAddress), NewIpInfo.IpAddress);
uint_to_szipaddr(uNewSubnetMask, ASIZE(NewIpInfo.SubnetMask), NewIpInfo.SubnetMask);
if (fFoundOldAddress == TRUE)
{
//
// Replace the old one.
//
m_pIpInfo[uFoundOldOffset] = NewIpInfo; // struct copy.
}
else
{
//
// Well add the new ip info to the head of the list.
//
if (m_uNum == m_uMax)
{
//
// We need to allocate more space.
// We somewhat arbitrarily reserve 2 spots
// NOTE: this will cause a change in the value of
// m_pIpInfo, m_uNum and m_uMax.
//
fRet = this->Set(m_uNum, m_pIpInfo, 2);
if (!fRet)
{
goto end;
}
}
//
// Move existing stuff one place down, to make place for the
// new one.
//
if (m_uNum >= m_uMax)
{
// Ahem, should never get here because we just added
// two extra spaces above.
fRet = FALSE;
goto end;
}
if (m_uNum)
{
// Note the regions overlap -- MoveMemory can handle this.
//
MoveMemory(m_pIpInfo+1, m_pIpInfo, m_uNum*sizeof(*m_pIpInfo));
}
//
// Add a new one -- we'll add it to the beginning.
//
m_pIpInfo[0] = NewIpInfo; // struct copy.
m_uNum++;
}
}
fRet = TRUE;
end:
// printf("<- modify: fRet=%lu, m_uNum=%lu m_uMax=%lu m_pIpInfo=0x%p\n",
// fRet, m_uNum, m_uMax, m_pIpInfo);
return fRet;
}
BOOL
NlbIpAddressList::sfn_validate_info(
const NLB_IP_ADDRESS_INFO &Info,
UINT &uIpAddress
)
{
WBEMSTATUS Status;
UINT uSubnetMask = 0;
Status = CfgUtilsValidateNetworkAddress(
Info.IpAddress,
&uIpAddress,
NULL,
NULL
);
if (!FAILED(Status))
{
Status = CfgUtilsValidateNetworkAddress(
Info.SubnetMask,
&uSubnetMask,
NULL,
NULL
);
}
return (!FAILED(Status));
}
UINT *
ipaddresses_from_ipaddressinfo(
const NLB_IP_ADDRESS_INFO *pInfo,
UINT NumAddresses
)
/*
Free return value using "delete" operator.
*/
{
UINT *rgOut = NULL;
if (NumAddresses == 0) goto end;
//
// Allocate space.
//
rgOut = new UINT[NumAddresses];
if (rgOut==NULL) goto end;
//
// Validate each address, thereby getting the ip address info.
//
for (UINT *pOut = rgOut; NumAddresses--; pOut++, pInfo++)
{
WBEMSTATUS wStat;
wStat = CfgUtilsValidateNetworkAddress(
pInfo->IpAddress,
pOut,
NULL,
NULL
);
if (FAILED(wStat))
{
TRACE_CRIT("%!FUNC! -- Validate address \"%ws\" failed!\n",
pInfo->IpAddress);
delete[] rgOut;
rgOut = NULL;
goto end;
}
}
end:
return rgOut;
}
BOOL
NlbIpAddressList::Apply(UINT NumNew, const NLB_IP_ADDRESS_INFO *pNewInfo)
/*
Set our internal list to be a permutation of the ip addresses in pInfo.
The permutation attempts to minimize the differences between the
new and the current version: basically the relative order of any adresses
that remain in new is preserved, and any new addresses are tacked on at
the end.
*/
{
BOOL fRet = FALSE;
UINT *rgOldIps = NULL;
UINT *rgNewIps = NULL;
NLB_IP_ADDRESS_INFO *rgNewInfo = NULL;
UINT NumFilled = 0;
UINT NumOld = m_uNum;
if (NumNew == 0)
{
this->Clear();
fRet = TRUE;
goto end;
}
if (NumOld!=0)
{
rgOldIps = ipaddresses_from_ipaddressinfo(
m_pIpInfo,
m_uNum
);
if (rgOldIps == NULL) goto end;
}
rgNewIps = ipaddresses_from_ipaddressinfo(
pNewInfo,
NumNew
);
if (rgNewIps==NULL) goto end;
rgNewInfo = new NLB_IP_ADDRESS_INFO[NumNew];
if (rgNewInfo == NULL)
{
TRACE_CRIT("%!FUNC! allocation failure!");
goto end;
}
//
// We try to preserve our current order of IP addresses
// as far as possible. To do this, we go through each ip address
// in our list in order -- if we find it in the new list, we
// add it to our new copy -- thereby preserving the order of all
// old IP addresses that are still present in the new list.
//
{
for (UINT uOld = 0; uOld < NumOld; uOld++)
{
UINT uOldIp = rgOldIps[uOld];
//
// See if it exists in new version -- if so add to new
//
for (UINT uNew=0; uNew<NumNew; uNew++)
{
if (uOldIp == rgNewIps[uNew])
{
// yes it's still present, keep it.
if (NumFilled<NumNew)
{
rgNewInfo[NumFilled]
= pNewInfo[uNew]; // struct copy
NumFilled++;
rgNewIps[uNew] = 0; // we use this later.
}
else
{
TRACE_CRIT("%!FUNC! Out of new addresses!");
fRet = FALSE;
goto end;
}
}
}
}
}
//
// Now tack on any cluster IP addresses not already added on.
//
{
//
// See if it exists in cluster version -- if so add to new
//
for (UINT uNew=0; uNew<NumNew; uNew++)
{
if (rgNewIps[uNew] != 0)
{
//
// yes it's a new cluster IP -- add it...
// (remember we set rgClusterIps[uCluster] to zero
// in the previous block, if we copied it over.
//
if (NumFilled<NumNew)
{
rgNewInfo[NumFilled]
= pNewInfo[uNew]; // struct copy
NumFilled++;
}
else
{
TRACE_CRIT("%!FUNC! Out of new addresses!");
fRet = FALSE;
goto end;
}
}
}
}
//
// At this point, we should have filled up all of the allocated space.
//
if (NumFilled != NumNew)
{
TRACE_CRIT("%!FUNC! NumNewAddressesFilled != NumNewAddresses!");
fRet = FALSE;
goto end;
}
//
// Now update our internal list.
//
delete[] m_pIpInfo;
m_pIpInfo = rgNewInfo;
m_uNum = m_uMax = NumNew;
rgNewInfo = NULL; // so it doesn't get deleted below.
fRet = TRUE;
end:
delete[] rgOldIps;
delete[] rgNewIps;
delete[] rgNewInfo;
return fRet;
}
const NLB_IP_ADDRESS_INFO *
find_ip_in_ipinfo(
LPCWSTR szIpToFind,
const NLB_IP_ADDRESS_INFO *pIpInfo,
UINT NumIpInfos
)
{
UINT uIpAddressToFind = 0;
UINT uIpAddress=0;
const NLB_IP_ADDRESS_INFO *pInfo = NULL;
WBEMSTATUS Status;
Status = CfgUtilsValidateNetworkAddress(
szIpToFind,
&uIpAddressToFind,
NULL,
NULL
);
if (Status == WBEM_NO_ERROR)
{
// Find location of old network address
for (UINT u=0; u<NumIpInfos; u++)
{
Status = CfgUtilsValidateNetworkAddress(
pIpInfo[u].IpAddress,
&uIpAddress,
NULL,
NULL
);
if (Status == WBEM_NO_ERROR)
{
if (uIpAddressToFind == uIpAddress)
{
// found it.
pInfo = &pIpInfo[u];
break;
}
}
}
}
return pInfo;
}