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.
738 lines
26 KiB
738 lines
26 KiB
//***************************************************************************
|
|
// WLBSPRIVATE.CPP
|
|
//
|
|
//
|
|
// Module: WMI Framework Instance provider
|
|
//
|
|
// Purpose: Contains routines that access the private fields of
|
|
// WLBS_REG_PARAMS
|
|
//
|
|
// Copyright (c)2001 Microsoft Corporation, All Rights Reserved
|
|
//
|
|
// History:
|
|
//
|
|
// 10/13/01 JosephJ Created (moved MyWlbsXXX functions from cfutil.cpp)
|
|
//
|
|
//***************************************************************************
|
|
|
|
//
|
|
// This macro allows us to access the private fields of WLBS_REG_PARAMS
|
|
//
|
|
#define WLBSAPI_INTERNAL_ONLY
|
|
|
|
|
|
#include "private.h"
|
|
|
|
|
|
VOID
|
|
CfgUtilSetHashedRemoteControlPassword(
|
|
IN OUT WLBS_REG_PARAMS *pParams,
|
|
IN DWORD dwHashedPassword
|
|
)
|
|
{
|
|
pParams->i_rct_password = dwHashedPassword;
|
|
}
|
|
|
|
DWORD
|
|
CfgUtilGetHashedRemoteControlPassword(
|
|
IN const WLBS_REG_PARAMS *pParams
|
|
)
|
|
{
|
|
return pParams->i_rct_password;
|
|
}
|
|
|
|
|
|
//
|
|
// Following (MyXXX) functions are to be used only on systems
|
|
// that do not have wlbsctrl.dll installed.
|
|
//
|
|
|
|
DWORD MyWlbsSetDefaults(PWLBS_REG_PARAMS reg_data)
|
|
{
|
|
reg_data -> install_date = 0;
|
|
reg_data -> i_verify_date = 0;
|
|
// reg_data -> cluster_nic_name [0] = _TEXT('\0');
|
|
reg_data -> i_parms_ver = CVY_DEF_VERSION;
|
|
reg_data -> i_virtual_nic_name [0] = _TEXT('\0');
|
|
reg_data -> host_priority = CVY_DEF_HOST_PRIORITY;
|
|
reg_data -> cluster_mode = CVY_DEF_CLUSTER_MODE;
|
|
reg_data -> persisted_states = CVY_DEF_PERSISTED_STATES;
|
|
ARRAYSTRCPY (reg_data -> cl_mac_addr, CVY_DEF_NETWORK_ADDR);
|
|
ARRAYSTRCPY (reg_data -> cl_ip_addr, CVY_DEF_CL_IP_ADDR);
|
|
ARRAYSTRCPY (reg_data -> cl_net_mask, CVY_DEF_CL_NET_MASK);
|
|
ARRAYSTRCPY (reg_data -> ded_ip_addr, CVY_DEF_DED_IP_ADDR);
|
|
ARRAYSTRCPY (reg_data -> ded_net_mask, CVY_DEF_DED_NET_MASK);
|
|
ARRAYSTRCPY (reg_data -> domain_name, CVY_DEF_DOMAIN_NAME);
|
|
reg_data -> alive_period = CVY_DEF_ALIVE_PERIOD;
|
|
reg_data -> alive_tolerance = CVY_DEF_ALIVE_TOLER;
|
|
reg_data -> num_actions = CVY_DEF_NUM_ACTIONS;
|
|
reg_data -> num_packets = CVY_DEF_NUM_PACKETS;
|
|
reg_data -> num_send_msgs = CVY_DEF_NUM_SEND_MSGS;
|
|
reg_data -> dscr_per_alloc = CVY_DEF_DSCR_PER_ALLOC;
|
|
reg_data -> max_dscr_allocs = CVY_DEF_MAX_DSCR_ALLOCS;
|
|
reg_data -> i_scale_client = CVY_DEF_SCALE_CLIENT;
|
|
reg_data -> i_cleanup_delay = CVY_DEF_CLEANUP_DELAY;
|
|
reg_data -> i_ip_chg_delay = CVY_DEF_IP_CHG_DELAY;
|
|
reg_data -> i_nbt_support = CVY_DEF_NBT_SUPPORT;
|
|
reg_data -> mcast_support = CVY_DEF_MCAST_SUPPORT;
|
|
reg_data -> i_mcast_spoof = CVY_DEF_MCAST_SPOOF;
|
|
reg_data -> mask_src_mac = CVY_DEF_MASK_SRC_MAC;
|
|
reg_data -> i_netmon_alive = CVY_DEF_NETMON_ALIVE;
|
|
reg_data -> i_effective_version = CVY_NT40_VERSION_FULL;
|
|
reg_data -> i_convert_mac = CVY_DEF_CONVERT_MAC;
|
|
reg_data -> i_num_rules = 0;
|
|
memset (reg_data -> i_port_rules, 0, sizeof (WLBS_PORT_RULE) * WLBS_MAX_RULES);
|
|
ARRAYSTRCPY (reg_data -> i_license_key, CVY_DEF_LICENSE_KEY);
|
|
reg_data -> i_rmt_password = CVY_DEF_RMT_PASSWORD;
|
|
reg_data -> i_rct_password = CVY_DEF_RCT_PASSWORD;
|
|
reg_data -> rct_port = CVY_DEF_RCT_PORT;
|
|
reg_data -> rct_enabled = CVY_DEF_RCT_ENABLED;
|
|
reg_data -> i_max_hosts = CVY_MAX_HOSTS;
|
|
reg_data -> i_max_rules = CVY_MAX_USABLE_RULES;
|
|
|
|
reg_data -> fIGMPSupport = CVY_DEF_IGMP_SUPPORT;
|
|
ARRAYSTRCPY(reg_data -> szMCastIpAddress, CVY_DEF_MCAST_IP_ADDR);
|
|
reg_data -> fIpToMCastIp = CVY_DEF_IP_TO_MCASTIP;
|
|
|
|
reg_data->bda_teaming.active = CVY_DEF_BDA_ACTIVE;
|
|
reg_data->bda_teaming.master = CVY_DEF_BDA_MASTER;
|
|
reg_data->bda_teaming.reverse_hash = CVY_DEF_BDA_REVERSE_HASH;
|
|
reg_data->bda_teaming.team_id[0] = CVY_DEF_BDA_TEAM_ID;
|
|
|
|
reg_data -> i_num_rules = 1;
|
|
|
|
// fill in the first port rule.
|
|
ARRAYSTRCPY(
|
|
reg_data->i_port_rules[0].virtual_ip_addr,
|
|
CVY_DEF_ALL_VIP
|
|
);
|
|
reg_data -> i_port_rules [0] . start_port = CVY_DEF_PORT_START;
|
|
reg_data -> i_port_rules [0] . end_port = CVY_DEF_PORT_END;
|
|
reg_data -> i_port_rules [0] . valid = TRUE;
|
|
reg_data -> i_port_rules [0] . mode = CVY_DEF_MODE;
|
|
reg_data -> i_port_rules [0] . mode_data . multi . equal_load = TRUE;
|
|
reg_data -> i_port_rules [0] . mode_data . multi . affinity = CVY_DEF_AFFINITY;
|
|
reg_data -> i_port_rules [0] . mode_data . multi . load = CVY_DEF_LOAD;
|
|
reg_data -> i_port_rules [0] . protocol = CVY_DEF_PROTOCOL;
|
|
CVY_RULE_CODE_SET(& reg_data -> i_port_rules [0]);
|
|
|
|
return WLBS_OK;
|
|
}
|
|
|
|
|
|
DWORD MyWlbsEnumPortRules
|
|
(
|
|
const PWLBS_REG_PARAMS reg_data,
|
|
PWLBS_PORT_RULE rules,
|
|
PDWORD num_rules
|
|
)
|
|
{
|
|
|
|
DWORD count_rules, i, index;
|
|
DWORD lowest_vip, lowest_port;
|
|
BOOL array_flags [WLBS_MAX_RULES];
|
|
WLBS_PORT_RULE sorted_rules [WLBS_MAX_RULES];
|
|
|
|
if ((reg_data == NULL) || (num_rules == NULL))
|
|
{
|
|
return WLBS_BAD_PARAMS;
|
|
}
|
|
|
|
if (*num_rules == 0)
|
|
rules = NULL;
|
|
/* this array is used for keeping track of which rules have already been retrieved */
|
|
/* This is needed since the rules are to be retrieved in the sorted order */
|
|
|
|
memset ( array_flags, 0, sizeof(BOOL) * WLBS_MAX_RULES );
|
|
|
|
count_rules = 0;
|
|
|
|
while ((count_rules < *num_rules) && (count_rules < reg_data -> i_num_rules))
|
|
{
|
|
i = 0;
|
|
|
|
/* find the first rule that has not been retrieved */
|
|
while ((! reg_data -> i_port_rules [i] . valid) || array_flags [i])
|
|
{
|
|
i++;
|
|
}
|
|
|
|
lowest_vip = htonl(IpAddressFromAbcdWsz(reg_data -> i_port_rules [i] . virtual_ip_addr));
|
|
lowest_port = reg_data -> i_port_rules [i] . start_port;
|
|
index = i;
|
|
|
|
/* Compare that rule with the other non-retrieved rules to get the rule with the
|
|
lowest VIP & start_port */
|
|
|
|
i++;
|
|
while (i < WLBS_MAX_RULES)
|
|
{
|
|
if (reg_data -> i_port_rules [i] . valid && ( ! array_flags [i] ))
|
|
{
|
|
DWORD current_vip = htonl(IpAddressFromAbcdWsz(reg_data -> i_port_rules [i] . virtual_ip_addr));
|
|
if ((current_vip < lowest_vip)
|
|
|| ((current_vip == lowest_vip) && (reg_data -> i_port_rules [i] . start_port < lowest_port)))
|
|
{
|
|
lowest_vip = current_vip;
|
|
lowest_port = reg_data -> i_port_rules [i] . start_port;
|
|
index = i;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
/* The array_flags [i] element is set to TRUE if the rule is retrieved */
|
|
array_flags [index] = TRUE;
|
|
sorted_rules [count_rules] = reg_data -> i_port_rules [index];
|
|
count_rules ++;
|
|
}
|
|
|
|
/* write the sorted rules back into the return array */
|
|
for (i = 0; i < count_rules; i++)
|
|
{
|
|
rules[i] = sorted_rules[i];
|
|
}
|
|
|
|
/* invalidate the remaining rules in the buffer */
|
|
for (i = count_rules; i < *num_rules; i++)
|
|
rules [i] . valid = FALSE;
|
|
|
|
if (*num_rules < reg_data -> i_num_rules)
|
|
{
|
|
*num_rules = reg_data -> i_num_rules;
|
|
return WLBS_TRUNCATED;
|
|
}
|
|
|
|
*num_rules = reg_data -> i_num_rules;
|
|
return WLBS_OK;
|
|
|
|
} /* end WlbsEnumPortRules */
|
|
|
|
|
|
VOID MyWlbsDeleteAllPortRules
|
|
(
|
|
PWLBS_REG_PARAMS reg_data
|
|
)
|
|
{
|
|
|
|
reg_data -> i_num_rules = 0;
|
|
|
|
ZeroMemory(reg_data -> i_port_rules, sizeof(reg_data -> i_port_rules));
|
|
|
|
|
|
} /* end WlbsDeleteAllPortRules */
|
|
|
|
|
|
DWORD MyWlbsAddPortRule
|
|
(
|
|
PWLBS_REG_PARAMS reg_data,
|
|
const PWLBS_PORT_RULE rule
|
|
)
|
|
{
|
|
|
|
int i;
|
|
DWORD vip;
|
|
|
|
if ((reg_data == NULL) || (rule == NULL))
|
|
{
|
|
return WLBS_BAD_PARAMS;
|
|
}
|
|
|
|
/* Check if there is space for the new rule */
|
|
if (reg_data -> i_num_rules == WLBS_MAX_RULES)
|
|
{
|
|
return WLBS_MAX_PORT_RULES;
|
|
}
|
|
|
|
/* check the rule for valid values */
|
|
|
|
/* check for non-zero vip and conflict with dip */
|
|
vip = IpAddressFromAbcdWsz(rule -> virtual_ip_addr);
|
|
if (vip == 0 || (INADDR_NONE == vip && lstrcmpi(rule -> virtual_ip_addr, CVY_DEF_ALL_VIP) != 0))
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
|
|
if (vip == IpAddressFromAbcdWsz(reg_data->ded_ip_addr))
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
|
|
/* first check the range of the start and end ports */
|
|
if ((rule -> start_port > rule -> end_port) ||
|
|
// CLEAN_64BIT (rule -> start_port < CVY_MIN_PORT) ||
|
|
(rule -> end_port > CVY_MAX_PORT))
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
|
|
/* check the protocol range */
|
|
if ((rule -> protocol < CVY_MIN_PROTOCOL) || (rule -> protocol > CVY_MAX_PROTOCOL))
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
|
|
/* check filtering mode to see whether it is within range */
|
|
if ((rule -> mode < CVY_MIN_MODE) || (rule -> mode > CVY_MAX_MODE))
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
|
|
/* check load weight and affinity if multiple hosts */
|
|
if (rule -> mode == CVY_MULTI)
|
|
{
|
|
if ((rule -> mode_data . multi . affinity < CVY_MIN_AFFINITY) ||
|
|
(rule -> mode_data . multi . affinity > CVY_MAX_AFFINITY))
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
|
|
if ((rule -> mode_data . multi . equal_load < CVY_MIN_EQUAL_LOAD) ||
|
|
(rule -> mode_data . multi . equal_load > CVY_MAX_EQUAL_LOAD))
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
|
|
if (! rule -> mode_data . multi . equal_load)
|
|
{
|
|
if ((rule -> mode_data . multi . load > CVY_MAX_LOAD))
|
|
//CLEAN_64BIT (rule -> mode_data . multi . load < CVY_MIN_LOAD) ||
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check handling priority range if single host */
|
|
if (rule -> mode == CVY_SINGLE)
|
|
{
|
|
if ((rule -> mode_data . single . priority < CVY_MIN_PRIORITY) ||
|
|
(rule -> mode_data . single . priority > CVY_MAX_PRIORITY))
|
|
{
|
|
return WLBS_BAD_PORT_PARAMS;
|
|
}
|
|
}
|
|
|
|
/* go through the rule list and then check for overlapping conditions */
|
|
for (i = 0; i < WLBS_MAX_RULES; i++)
|
|
{
|
|
if (reg_data -> i_port_rules[i] . valid == TRUE)
|
|
{
|
|
if ((IpAddressFromAbcdWsz(reg_data -> i_port_rules[i] . virtual_ip_addr) == vip)
|
|
&& (( (reg_data -> i_port_rules[i] . start_port <= rule -> start_port) &&
|
|
(reg_data -> i_port_rules[i] . end_port >= rule -> start_port)) ||
|
|
( (reg_data -> i_port_rules[i] . start_port >= rule -> start_port) &&
|
|
(reg_data -> i_port_rules[i] . start_port <= rule -> end_port))))
|
|
{
|
|
return WLBS_PORT_OVERLAP;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* go through the rule list and find out the first empty spot
|
|
and write out the port rule */
|
|
|
|
for (i = 0 ; i < WLBS_MAX_RULES ; i++)
|
|
{
|
|
if (reg_data -> i_port_rules[i] . valid == FALSE)
|
|
{
|
|
reg_data -> i_num_rules ++ ;
|
|
reg_data -> i_port_rules [i] = *rule;
|
|
reg_data -> i_port_rules [i] . valid = TRUE;
|
|
CVY_RULE_CODE_SET(& reg_data -> i_port_rules [i]);
|
|
return WLBS_OK;
|
|
}
|
|
}
|
|
|
|
return WLBS_MAX_PORT_RULES;
|
|
|
|
} /* end WlbsAddPortRule */
|
|
|
|
|
|
BOOL MyWlbsValidateParams(
|
|
const PWLBS_REG_PARAMS paramp
|
|
)
|
|
{
|
|
// Following stolen from wlbs\api
|
|
#define WLBS_FIELD_LOW 0
|
|
#define WLBS_FIELD_HIGH 255
|
|
#define WLBS_IP_FIELD_ZERO_LOW 1
|
|
#define WLBS_IP_FIELD_ZERO_HIGH 223
|
|
|
|
|
|
bool fRet = FALSE;
|
|
DWORD idx;
|
|
IN_ADDR dwIPAddr;
|
|
CHAR * szIPAddr;
|
|
DWORD num_rules;
|
|
WLBS_PORT_RULE *port_rule;
|
|
|
|
/* verify and if necessary reset the parameters */
|
|
|
|
//
|
|
// We don't validate the lower bound for unsigned words when the lower bound is 0. Otherwise we
|
|
// get a compiler warning, promoted to an error, because such a test can't fail
|
|
//
|
|
// Ignore lower bound checking
|
|
//
|
|
CVY_CHECK_MAX (paramp -> i_scale_client, CVY_MAX_SCALE_CLIENT);
|
|
|
|
CVY_CHECK_MAX (paramp -> i_nbt_support, CVY_MAX_NBT_SUPPORT);
|
|
|
|
CVY_CHECK_MAX (paramp -> mcast_support, CVY_MAX_MCAST_SUPPORT);
|
|
|
|
CVY_CHECK_MAX (paramp -> i_mcast_spoof, CVY_MAX_MCAST_SPOOF);
|
|
|
|
CVY_CHECK_MAX (paramp -> mask_src_mac, CVY_MAX_MASK_SRC_MAC);
|
|
|
|
CVY_CHECK_MAX (paramp -> i_netmon_alive, CVY_MAX_NETMON_ALIVE);
|
|
|
|
CVY_CHECK_MAX (paramp -> i_convert_mac, CVY_MAX_CONVERT_MAC);
|
|
|
|
CVY_CHECK_MAX (paramp -> rct_port, CVY_MAX_RCT_PORT);
|
|
|
|
CVY_CHECK_MAX (paramp -> rct_enabled, CVY_MAX_RCT_ENABLED);
|
|
|
|
CVY_CHECK_MAX (paramp -> i_cleanup_delay, CVY_MAX_CLEANUP_DELAY);
|
|
|
|
CVY_CHECK_MAX (paramp -> i_ip_chg_delay, CVY_MAX_IP_CHG_DELAY);
|
|
|
|
CVY_CHECK_MAX (paramp -> i_num_rules, CVY_MAX_NUM_RULES);
|
|
|
|
CVY_CHECK_MAX (paramp -> cluster_mode, CVY_MAX_CLUSTER_MODE);
|
|
//
|
|
// End Ignore lower bound checking
|
|
//
|
|
|
|
//
|
|
// CVY_NAME_VERSION is not validated since its value is used and manipulated before we get here
|
|
// CVY_NAME_LICENSE_KEY is not validated since it can take any value.
|
|
// RMT_PASSWORD is not validated since it can take any storable value
|
|
// RCT_PASSWORD is not validated since it can take any storable value
|
|
// CVY_NAME_IGMP_SUPPORT is not validated because it is of BOOL type and can thus take any value
|
|
// CVY_NAME_IP_TO_MCASTIP is not validated because it is of BOOL type and can thus take any value
|
|
//
|
|
|
|
CVY_CHECK_MIN (paramp -> alive_period, CVY_MIN_ALIVE_PERIOD);
|
|
CVY_CHECK_MAX (paramp -> alive_period, CVY_MAX_ALIVE_PERIOD);
|
|
|
|
CVY_CHECK_MIN (paramp -> alive_tolerance, CVY_MIN_ALIVE_TOLER);
|
|
CVY_CHECK_MAX (paramp -> alive_tolerance, CVY_MAX_ALIVE_TOLER);
|
|
|
|
CVY_CHECK_MIN (paramp -> num_actions, CVY_MIN_NUM_ACTIONS);
|
|
CVY_CHECK_MAX (paramp -> num_actions, CVY_MAX_NUM_ACTIONS);
|
|
|
|
CVY_CHECK_MIN (paramp -> num_packets, CVY_MIN_NUM_PACKETS);
|
|
CVY_CHECK_MAX (paramp -> num_packets, CVY_MAX_NUM_PACKETS);
|
|
|
|
CVY_CHECK_MIN (paramp -> dscr_per_alloc, CVY_MIN_DSCR_PER_ALLOC);
|
|
CVY_CHECK_MAX (paramp -> dscr_per_alloc, CVY_MAX_DSCR_PER_ALLOC);
|
|
|
|
CVY_CHECK_MIN (paramp -> max_dscr_allocs, CVY_MIN_MAX_DSCR_ALLOCS);
|
|
CVY_CHECK_MAX (paramp -> max_dscr_allocs, CVY_MAX_MAX_DSCR_ALLOCS);
|
|
|
|
CVY_CHECK_MIN (paramp -> num_send_msgs, (paramp -> i_max_hosts + 1) * 2);
|
|
CVY_CHECK_MAX (paramp -> num_send_msgs, (paramp -> i_max_hosts + 1) * 10);
|
|
|
|
CVY_CHECK_MIN (paramp -> host_priority, CVY_MIN_HOST_PRIORITY);
|
|
CVY_CHECK_MAX (paramp -> host_priority, CVY_MAX_HOST_PRIORITY);
|
|
|
|
/* If the cluster IP address is not 0.0.0.0, then make sure the IP address is valid. */
|
|
if (lstrcmpi(paramp->cl_ip_addr, CVY_DEF_CL_IP_ADDR)) {
|
|
/* Check the validity of the IP address. */
|
|
if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->cl_ip_addr)))
|
|
goto error;
|
|
|
|
/* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
|
|
address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
|
|
the IP address string (which is used by other parts of NLB, such as the UI)
|
|
consistent, we convert back to a string. */
|
|
if (!(szIPAddr = inet_ntoa(dwIPAddr)))
|
|
goto error;
|
|
|
|
/* Convert the ASCII string to unicode. */
|
|
if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->cl_ip_addr, WLBS_MAX_CL_IP_ADDR + 1))
|
|
goto error;
|
|
}
|
|
|
|
/* If the cluster netmask is not 0.0.0.0, then make sure the netmask is valid. */
|
|
if (lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK)) {
|
|
/* Check the validity of the IP address. */
|
|
if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->cl_net_mask)))
|
|
goto error;
|
|
|
|
/* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
|
|
address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
|
|
the IP address string (which is used by other parts of NLB, such as the UI)
|
|
consistent, we convert back to a string. */
|
|
if (!(szIPAddr = inet_ntoa(dwIPAddr)))
|
|
goto error;
|
|
|
|
/* Convert the ASCII string to unicode. */
|
|
if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->cl_net_mask, WLBS_MAX_CL_NET_MASK + 1))
|
|
goto error;
|
|
}
|
|
|
|
/* If the dedicated IP address is not 0.0.0.0, then make sure the IP address is valid. */
|
|
if (lstrcmpi(paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR)) {
|
|
/* Check the validity of the IP address. */
|
|
if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->ded_ip_addr)))
|
|
goto error;
|
|
|
|
/* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
|
|
address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
|
|
the IP address string (which is used by other parts of NLB, such as the UI)
|
|
consistent, we convert back to a string. */
|
|
if (!(szIPAddr = inet_ntoa(dwIPAddr)))
|
|
goto error;
|
|
|
|
/* Convert the ASCII string to unicode. */
|
|
if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->ded_ip_addr, WLBS_MAX_DED_IP_ADDR + 1))
|
|
goto error;
|
|
}
|
|
|
|
/* If the dedicated netmask is not 0.0.0.0, then make sure the netmask is valid. */
|
|
if (lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK)) {
|
|
/* Check the validity of the IP address. */
|
|
if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->ded_net_mask)))
|
|
goto error;
|
|
|
|
/* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
|
|
address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
|
|
the IP address string (which is used by other parts of NLB, such as the UI)
|
|
consistent, we convert back to a string. */
|
|
if (!(szIPAddr = inet_ntoa(dwIPAddr)))
|
|
goto error;
|
|
|
|
/* Convert the ASCII string to unicode. */
|
|
if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->ded_net_mask, WLBS_MAX_DED_NET_MASK + 1))
|
|
goto error;
|
|
}
|
|
|
|
/* Verify that the port rule VIP is valid,
|
|
Also, convert the port rule VIPs that might be in the x.x.x or x.x or x form to x.x.x.x */
|
|
idx = 0;
|
|
num_rules = paramp -> i_num_rules;
|
|
while (idx < num_rules)
|
|
{
|
|
port_rule = ¶mp->i_port_rules[idx];
|
|
|
|
/* Check if the port rule is valid and the vip is not "All Vip" */
|
|
if (port_rule->valid && lstrcmpi(port_rule->virtual_ip_addr, CVY_DEF_ALL_VIP))
|
|
{
|
|
/* Get IP Address into DWORD form */
|
|
if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(port_rule->virtual_ip_addr)))
|
|
goto error;
|
|
|
|
/* Check for validity of IP Address */
|
|
if ((dwIPAddr.S_un.S_un_b.s_b1 < WLBS_IP_FIELD_ZERO_LOW)
|
|
|| (dwIPAddr.S_un.S_un_b.s_b1 > WLBS_IP_FIELD_ZERO_HIGH)
|
|
|| (dwIPAddr.S_un.S_un_b.s_b2 < WLBS_FIELD_LOW)
|
|
|| (dwIPAddr.S_un.S_un_b.s_b2 > WLBS_FIELD_HIGH)
|
|
|| (dwIPAddr.S_un.S_un_b.s_b3 < WLBS_FIELD_LOW)
|
|
|| (dwIPAddr.S_un.S_un_b.s_b3 > WLBS_FIELD_HIGH)
|
|
|| (dwIPAddr.S_un.S_un_b.s_b4 < WLBS_FIELD_LOW)
|
|
|| (dwIPAddr.S_un.S_un_b.s_b4 > WLBS_FIELD_HIGH))
|
|
goto error;
|
|
|
|
/* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
|
|
address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
|
|
the IP address string (which is used by other parts of NLB, such as the UI)
|
|
consistent, we convert back to a string. */
|
|
if (!(szIPAddr = inet_ntoa(dwIPAddr)))
|
|
goto error;
|
|
|
|
/* Convert the ASCII string to unicode. */
|
|
if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, port_rule->virtual_ip_addr, WLBS_MAX_CL_IP_ADDR + 1))
|
|
goto error;
|
|
}
|
|
idx++;
|
|
}
|
|
|
|
/* If either the cluster IP address or the cluster netmask is not 0.0.0.0,
|
|
then make sure the they are a valid IP address/netmask pair. */
|
|
if (lstrcmpi(paramp->cl_ip_addr, CVY_DEF_CL_IP_ADDR) || lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK)) {
|
|
/* If they have specified a cluster IP address, but no netmask, then fill it in for them. */
|
|
if (!lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK))
|
|
{
|
|
ParamsGenerateSubnetMask(paramp->cl_ip_addr, paramp->cl_net_mask, ASIZECCH(paramp->cl_net_mask));
|
|
}
|
|
|
|
/* Check for valid cluster IP address/netmask pairs. */
|
|
if (!IsValidIPAddressSubnetMaskPair(paramp->cl_ip_addr, paramp->cl_net_mask))
|
|
goto error;
|
|
|
|
/* Check to make sure that the cluster netmask is contiguous. */
|
|
if (!IsContiguousSubnetMask(paramp->cl_net_mask))
|
|
goto error;
|
|
|
|
/* Check to make sure that the dedicated IP and cluster IP are not the same. */
|
|
if (!wcscmp(paramp->ded_ip_addr, paramp->cl_ip_addr))
|
|
goto error;
|
|
}
|
|
|
|
/* If either the dedicated IP address or the dedicated netmask is not 0.0.0.0,
|
|
then make sure the they are a valid IP address/netmask pair. */
|
|
if (lstrcmpi(paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR) || lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK)) {
|
|
/* If they have specified a cluster IP address, but no netmask, then fill it in for them. */
|
|
if (!lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK))
|
|
{
|
|
ParamsGenerateSubnetMask(paramp->ded_ip_addr, paramp->ded_net_mask, ASIZECCH(paramp->ded_net_mask));
|
|
}
|
|
|
|
/* Check for valid dedicated IP address/netmask pairs. */
|
|
if (!IsValidIPAddressSubnetMaskPair(paramp->ded_ip_addr, paramp->ded_net_mask))
|
|
goto error;
|
|
|
|
/* Check to make sure that the dedicated netmask is contiguous. */
|
|
if (!IsContiguousSubnetMask(paramp->ded_net_mask))
|
|
goto error;
|
|
}
|
|
|
|
/* Check the mac address if the convert_mac flag is not set */
|
|
if ( ! paramp -> i_convert_mac)
|
|
{
|
|
PWCHAR p1, p2;
|
|
WCHAR mac_addr [WLBS_MAX_NETWORK_ADDR + 1];
|
|
DWORD i, j;
|
|
BOOL flag = TRUE;
|
|
|
|
ARRAYSTRCPY (mac_addr, paramp -> cl_mac_addr);
|
|
|
|
p2 = p1 = mac_addr;
|
|
|
|
for (i = 0 ; i < 6 ; i++)
|
|
{
|
|
if (*p2 == _TEXT('\0'))
|
|
{
|
|
flag = FALSE;
|
|
break;
|
|
}
|
|
|
|
j = _tcstoul (p1, &p2, 16);
|
|
|
|
if ( j > 255)
|
|
{
|
|
flag = FALSE;
|
|
break;
|
|
}
|
|
|
|
if ( ! (*p2 == _TEXT('-') || *p2 == _TEXT(':') || *p2 == _TEXT('\0')) )
|
|
{
|
|
flag = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (*p2 == _TEXT('\0') && i < 5)
|
|
{
|
|
flag = FALSE;
|
|
break;
|
|
}
|
|
|
|
p1 = p2 + 1;
|
|
p2 = p1;
|
|
|
|
}
|
|
|
|
|
|
if (!flag)
|
|
{
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
if (paramp->fIGMPSupport && !paramp->mcast_support)
|
|
{
|
|
//
|
|
// IGMP can not be enabled in unicast mode
|
|
//
|
|
|
|
goto error;
|
|
}
|
|
|
|
if (paramp->mcast_support && paramp->fIGMPSupport && !paramp->fIpToMCastIp)
|
|
{
|
|
//
|
|
// Verify that the multicast IP is a valid IP form. Ignore default value case since it isn't a valid IP.
|
|
//
|
|
if (lstrcmpi(paramp -> szMCastIpAddress, CVY_DEF_MCAST_IP_ADDR)) {
|
|
/* Check the validity of the IP address. */
|
|
if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp -> szMCastIpAddress)))
|
|
goto error;
|
|
|
|
/* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
|
|
address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
|
|
the IP address string (which is used by other parts of NLB, such as the UI)
|
|
consistent, we convert back to a string. */
|
|
if (!(szIPAddr = inet_ntoa(dwIPAddr)))
|
|
goto error;
|
|
|
|
/* Convert the ASCII string to unicode. */
|
|
if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp -> szMCastIpAddress, WLBS_MAX_CL_IP_ADDR + 1))
|
|
goto error;
|
|
}
|
|
|
|
//
|
|
// Multicast mode with IGMP enabled, and user specified an multicast IP address,
|
|
// The multicast IP address should be in the range of (224-239).x.x.x
|
|
// but NOT (224-239).0.0.x or (224-239).128.0.x.
|
|
//
|
|
|
|
DWORD dwMCastIp = IpAddressFromAbcdWsz(paramp->szMCastIpAddress);
|
|
|
|
if ((dwMCastIp & 0xf0) != 0xe0 ||
|
|
(dwMCastIp & 0x00ffff00) == 0 ||
|
|
(dwMCastIp & 0x00ffff00) == 0x00008000)
|
|
{
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
/* Generate the MAC address. */
|
|
ParamsGenerateMAC(paramp->cl_ip_addr, paramp->cl_mac_addr, ASIZECCH(paramp->cl_mac_addr), paramp->szMCastIpAddress, ASIZECCH(paramp->szMCastIpAddress), paramp->i_convert_mac,
|
|
paramp->mcast_support, paramp->fIGMPSupport, paramp->fIpToMCastIp);
|
|
|
|
//
|
|
// We only process bda information if bda teaming is active. We can ignore these properties if it isn't. Dependencies
|
|
// such as WriteRegParam will check this too to see if they should process the information.
|
|
//
|
|
if (paramp -> bda_teaming . active) {
|
|
GUID TeamGuid;
|
|
HRESULT hr;
|
|
|
|
//
|
|
// We don't validate the lower bound for unsigned words when the lower bound is 0. Otherwise we
|
|
// get a compiler warning, promoted to an error, because such a test can't fail
|
|
//
|
|
// Ignore lower bound checking
|
|
//
|
|
CVY_CHECK_MAX (paramp -> bda_teaming . master, 1);
|
|
|
|
CVY_CHECK_MAX (paramp -> bda_teaming . reverse_hash, 1);
|
|
//
|
|
// End Ignore lower bound checking
|
|
//
|
|
|
|
//
|
|
// A teaming ID must be a GUID. Validate that it is, but we don't care what value. This means we ignore
|
|
// the content of TeamGuid.
|
|
//
|
|
hr = CLSIDFromString(paramp -> bda_teaming . team_id, &TeamGuid);
|
|
|
|
// If the conversion fails, bail out - the team ID must not have been a GUID
|
|
if (hr != NOERROR) {
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
fRet = TRUE;
|
|
goto end;
|
|
|
|
error:
|
|
fRet = FALSE;
|
|
goto end;
|
|
|
|
end:
|
|
return fRet;
|
|
}
|
|
|