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.
 
 
 
 
 
 

5534 lines
139 KiB

/*++ Copyright(c) 2001 Microsoft Corporation
Module Name:
NLB Manager
File Name:
tprov.cpp
Abstract:
Test harness for nlb manager provider code
History:
04/08/01 JosephJ Created
--*/
#include "tprov.h"
#include "tprov.tmh"
BOOL g_Silent = FALSE;
HANDLE g_hEventLog = NULL; // defined here to get ..\updatecf.cpp to link ok.
BOOL g_Impersonate=FALSE;
int g_nRetCode = 0; // return code for this program.
#define RETCODE_NO_ERROR 0
#define RETCODE_UPDATE_FAILED 1
#define RETCODE_NEW_CONFIG_DOESNT_MATCH 2
HMODULE ghModule;
void test_alignment(void);
void test_local_logger(void);
void test_encrypt_memory(void);
BOOL
GetPassword(
PWSTR szBuffer,
DWORD dwLength,
DWORD *pdwLengthReturn
);
#define ARRAY_LENGTH(_array) (sizeof(_array)/sizeof(_array[0]))
typedef enum
{
DO_USAGE,
DO_WMINICLIST,
DO_NICLIST,
DO_IPADDR,
DO_NLBCFG,
DO_NLBBIND,
DO_UPDATE,
DO_WMIUPDATE,
DO_CLEANREG
} COMMAND_TYPE;
typedef enum
{
KW_ADAPTER_LIST,
KW_UPDATE,
KW_QUIT,
KW_HELP,
KW_ADAPTER_GUID,
KW_NETWORK_ADDRESSES,
KW_PARTIAL_UPDATE,
KW_NLB_BOUND,
KW_CLUSTER_NETWORK_ADDRESS,
KW_CLUSTER_NAME,
KW_TRAFFIC_MODE,
KW_PORT_RULES,
KW_HOST_PRIORITY,
KW_DEDICATED_NETWORK_ADDRESS,
KW_CLUSTER_MODE_ON_START,
KW_PERSIST_SUSPEND_ON_REBOOT,
KW_REMOTE_CONTROL_ENABLED,
KW_PASSWORD,
KW_LIST,
KW_DOT,
KW_MODIFY_NETWORK_ADDRESS,
KW_IPADDR, // test command
KW_NLBBIND, // test command
KW_NLBCFG, // test command
KW_YES,
KW_NO,
//
// Control cluster/port related
//
KW_CONTROL,
KW_START,
KW_STOP,
KW_DRAIN_STOP,
KW_SUSPEND,
KW_RESUME,
KW_ENABLE,
KW_DISABLE,
KW_DRAIN,
KW_QUERY,
KW_VIP,
KW_PORT,
KW_MAIN_SHELL, // implicit keyword if no command present in cmdline.
KW_UNKNOWN
} KEYWORD;
VOID do_usage(VOID);
VOID do_niclist(LPCWSTR szFriendlyName, LPWSTR *pszGuid);
VOID do_wminiclist(LPCWSTR szFriendlyName, LPWSTR *pszGuid);
VOID do_ipaddr(VOID);
VOID do_nlbcfg(VOID);
VOID do_nlbbind(VOID);
VOID do_update(VOID);
VOID do_wmiupdate(VOID);
VOID do_cleanreg(VOID);
void parse_main(int argc, WCHAR* argv[]);
VOID test_add_ips(LPCWSTR szNic);
VOID test_bind_nlb(LPCWSTR szNic);
VOID test_cfg_nlb(LPCWSTR szNic);
VOID test_update(LPCWSTR szMachine, LPCWSTR szNic);
void test(int argc, WCHAR* argv[]);
void test(int argc, WCHAR* argv[]);
void test_safearray(void);
VOID test_exfcfgclass(void);
void test_read_keyword(void);
VOID test_port_rule_string(VOID);
void test_vectors(void);
void test_maps(void);
void test_validate_network_address(void);
void test_nlbipaddresslist(void);
void test_ioctl_alignment(void);
BOOL read_guid(LPWSTR *pszNic);
BOOL read_machinename(LPWSTR *pszNic);
BOOL read_password(VOID);
BOOL get_guid_by_friendly_name(VOID);
BOOL valid_guid(LPCWSTR szGuid);
KEYWORD
parse_args(int argc, WCHAR* argv[]);
typedef struct
{
KEYWORD kw;
LPCWSTR sz;
} KEYWORD_MAP;
const KEYWORD_MAP KeywordMap[] =
{
{KW_ADAPTER_LIST, L"AdapterList"},
{KW_ADAPTER_LIST, L"AL"},
{KW_QUIT, L"Quit"},
{KW_QUIT, L"Q"},
{KW_UPDATE, L"Update"},
{KW_UPDATE, L"U"},
{KW_HELP, L"Help"},
{KW_HELP, L"H"},
{KW_HELP, L"?"},
{KW_ADAPTER_GUID, L"AdapterGuid"},
{KW_ADAPTER_GUID, L"AG"},
{KW_NETWORK_ADDRESSES, L"NetworkAddresses"},
{KW_NETWORK_ADDRESSES, L"NA"},
{KW_PARTIAL_UPDATE, L"PartialUpdate"},
{KW_PARTIAL_UPDATE, L"PU"},
{KW_NLB_BOUND, L"NlbBound"},
{KW_NLB_BOUND, L"NB"},
{KW_CLUSTER_NETWORK_ADDRESS, L"ClusterNetworkAddress"},
{KW_CLUSTER_NETWORK_ADDRESS, L"CNA"},
{KW_CLUSTER_NAME, L"ClusterName"},
{KW_CLUSTER_NAME, L"CN"},
{KW_TRAFFIC_MODE, L"TrafficMode"},
{KW_TRAFFIC_MODE, L"TM"},
{KW_PORT_RULES, L"PortRules"},
{KW_PORT_RULES, L"PR"},
{KW_HOST_PRIORITY, L"HostPriority"},
{KW_HOST_PRIORITY, L"HP"},
{KW_DEDICATED_NETWORK_ADDRESS, L"DedicatedNetworkAddress"},
{KW_DEDICATED_NETWORK_ADDRESS, L"DNA"},
{KW_CLUSTER_MODE_ON_START, L"ClusterModeOnStart"},
{KW_CLUSTER_MODE_ON_START, L"CMOS"},
{KW_PERSIST_SUSPEND_ON_REBOOT, L"PersistSuspend"},
{KW_PERSIST_SUSPEND_ON_REBOOT, L"PS"},
{KW_REMOTE_CONTROL_ENABLED, L"RemoteControlEnabled"},
{KW_REMOTE_CONTROL_ENABLED, L"RCE"},
{KW_PASSWORD, L"Password"},
{KW_PASSWORD, L"P"},
{KW_LIST, L"List"},
{KW_LIST, L"L"},
{KW_DOT, L"."},
{KW_MODIFY_NETWORK_ADDRESS, L"ModifyNetworkAddress"},
{KW_MODIFY_NETWORK_ADDRESS, L"MNA"},
{KW_IPADDR, L"ipaddr"}, // test command -- only cmdline param
{KW_NLBBIND, L"nlbbind"}, // test command -- only cmdline param
{KW_NLBCFG, L"nlbcfg"}, // test command -- only cmdline param
{KW_YES, L"yes"},
{KW_YES, L"y"},
{KW_NO, L"no"},
{KW_NO, L"n"},
//
// Control cluster/port related
//
{KW_CONTROL, L"control"},
{KW_CONTROL, L"cl"},
{KW_START, L"start"},
{KW_START, L"st"},
{KW_STOP, L"stop"},
{KW_STOP, L"sp"},
{KW_DRAIN_STOP, L"drainstop"},
{KW_DRAIN_STOP, L"ds"},
{KW_SUSPEND, L"suspend"},
{KW_SUSPEND, L"su"},
{KW_RESUME, L"resume"},
{KW_RESUME, L"re"},
{KW_ENABLE, L"enable"},
{KW_ENABLE, L"en"},
{KW_DISABLE, L"disable"},
{KW_DISABLE, L"di"},
{KW_DRAIN, L"drain"},
{KW_DRAIN, L"dn"},
{KW_QUERY, L"query"},
{KW_QUERY, L"qu"},
{KW_VIP, L"vip"},
{KW_PORT, L"port"},
{KW_UNKNOWN, NULL} // Must be last
};
KEYWORD parse_adapter_list(VOID);
KEYWORD parse_update(VOID);
KEYWORD parse_main_help(VOID);
KEYWORD lookup_keyword(LPCWSTR szKeyword);
struct
{
// *_LENGTH ==> doesn't include space for ending NULL
#define MAX_MACHINE_NAME_LENGTH 256
#define MAX_USER_NAME_LENGTH 256
#define MAX_PASSWORD_LENGTH 256
#define INPUT_BUFFER_LENGTH 1024
#define NLB_MAX_FRIENDLY_NAME_LENGTH 256
WCHAR MachineName[MAX_MACHINE_NAME_LENGTH+1];
WCHAR UserName[MAX_USER_NAME_LENGTH+1];
WCHAR Password[MAX_PASSWORD_LENGTH+1];
WCHAR InputBuffer[INPUT_BUFFER_LENGTH+1];
WCHAR AdapterGuid[NLB_GUID_STRING_SIZE];
WCHAR FriendlyName[NLB_MAX_FRIENDLY_NAME_LENGTH+1];
BOOL fReadPassword;
BOOL fUseWmi;
BOOL fLocalHost;
BOOL fGotGuid;
BOOL fGotFriendlyName;
BOOL fRunOnce;
} g;
void
display_config(
LPCWSTR szNicGuid,
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
);
void
display_port_rules(
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
);
void
display_config2(
LPCWSTR szNicGuid,
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
);
VOID
display_ip_info(
IN UINT NumIpAddresses,
IN NLB_IP_ADDRESS_INFO *pIpInfo
);
VOID
display_ip_info2(
IN UINT NumIpAddresses,
IN NLB_IP_ADDRESS_INFO *pIpInfo
);
WBEMSTATUS
read_ip_info(
IN LPCWSTR szNic,
OUT UINT *pNumIpAddresses,
OUT NLB_IP_ADDRESS_INFO **ppIpInfo
);
BOOL
WINAPI
MyCtrlHandlerRoutine(
DWORD dwCtrlType // control signal type
)
{
//
// We de-initialize here so that we don't get an AV when the user types
// CtrlC
//
CfgUtilDeitialize();
return FALSE;
}
int __cdecl wmain(int argc, WCHAR* argv[], WCHAR* envp[])
{
(void) SetConsoleCtrlHandler(
MyCtrlHandlerRoutine, // handler function
TRUE // TRUE== add
);
//
// Enable tracing
//
WPP_INIT_TRACING(L"Microsoft\\NLB\\TPROV");
ghModule = GetModuleHandle(NULL);
#if 0
test_encrypt_memory();
// test_local_logger();
// test_alignment();
// test_port_rule_string();
// test_safearray();
// test_tmgr(argc, argv);
// test_exfcfgclass();
// test_vectors();
// test_maps();
// test_validate_network_address();
// test_read_keyword();
// test_nlbipaddresslist();
// test_ioctl_alignment();
#else
// NlbHostFake();
//
// Enable the "SeLoadDriverPrivilege" privilege in the process access token.
// This is needed in the case when the server is local (ie. same machine).
// Do NOT check for the return value since this function will fail when called
// as a non-admin. It is not only ok but also necessary to ignore the failure of
// this function because:
// 1. We already check in the wmi provider that the caller is an administrator on
// the server and if the privilege is enabled. This is why it is ok to ignore
// failures in this function.
// 2. Non-admins can run nlb manager. They only need to be admins on the server.
// This is why it is necessary to ignore failures in this function.
//
CfgUtils_Enable_Load_Unload_Driver_Privilege();
CfgUtilInitialize(
TRUE, // TRUE == init as server (use wlbsctrl apis if pos)
FALSE // FALSE == Do not disable Ping (i.e, enable ping)
);
NlbConfigurationUpdate::StaticInitialize();
parse_main(argc, argv);
NlbConfigurationUpdate::PrepareForDeinitialization();
NlbConfigurationUpdate::StaticDeinitialize();
CfgUtilDeitialize();
#endif
//
// Disable tracing
//
WPP_CLEANUP();
return g_nRetCode;
}
NLB_EXTENDED_CLUSTER_CONFIGURATION MyOldCfg;
NLB_EXTENDED_CLUSTER_CONFIGURATION MyNewCfg;
VOID
display_log(WCHAR *pLog)
{
static UINT previous_length;
UINT current_length;
current_length = wcslen(pLog);
if (previous_length > current_length)
{
previous_length = 0;
}
wprintf(L"%ws", pLog+previous_length);
previous_length = current_length;
}
LPCWSTR NicGuids[] = {
L"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}",
L"{B2CD5533-5091-4F49-B80F-A07844B14209}",
L"{EBE09517-07B4-4E88-AAF1-E06F5540608B}",
L"{ABEA4318-5EE8-4DEC-AF3C-B4AEDE61454E}",
L"{66A1869A-BF85-4D95-BBAB-07FA5B4449D4}",
L"{AEEE83AF-AA48-4599-94BB-7C458D63CEED}",
L"{D0536EEE-2CE0-4E8D-BFEC-0A608CFD81B9}"
};
UINT Trial;
void test(int argc, WCHAR* argv[])
{
KEYWORD cmd;
cmd = parse_args(argc, argv);
switch(cmd)
{
case KW_UNKNOWN: do_usage();
break;
case KW_ADAPTER_LIST: do_niclist(NULL, NULL);
break;
case KW_IPADDR: do_ipaddr();
break;
case KW_NLBCFG: do_nlbcfg();
break;
case KW_NLBBIND: do_nlbbind();
break;
case KW_UPDATE: do_update();
break;
#if 0
case KW_WMINICLIST: do_wminiclist(NULL, NULL);
break;
case KW_WMIUPDATE: do_wmiupdate();
break;
case KW_CLEANREG: do_cleanreg();
break;
#endif // 0
}
return;
}
void
display_config(
LPCWSTR szNicGuid,
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
)
{
LPWSTR szFriendlyName = NULL;
if (g_Silent) return;
WBEMSTATUS Status;
Status = pCfg->GetFriendlyName(&szFriendlyName);
if (FAILED(Status))
{
szFriendlyName = NULL;
}
printf(
"\nNLB Configuration for %ws \"%ws\" %ws\n",
szNicGuid,
(szFriendlyName == NULL) ? L"" : szFriendlyName,
pCfg->fDHCP ? L"(DHCP)" : L""
);
printf("\tfValidNlbCfg=%d\n", pCfg->fValidNlbCfg);
printf("\tGeneration=%d\n", pCfg->Generation);
printf("\tfBound=%d\n", pCfg->fBound);
printf("\tfAddDedicatedIp=%d\n", pCfg->fAddDedicatedIp);
UINT AddrCount = pCfg->NumIpAddresses;
display_ip_info(AddrCount, pCfg->pIpAddressInfo);
if (pCfg->fBound)
{
printf("\n");
printf("\tNLB configuration:\n");
if (pCfg->fValidNlbCfg)
{
printf("\t\tClusterIP: {%ws,%ws}\n",
pCfg->NlbParams.cl_ip_addr,
pCfg->NlbParams.cl_net_mask
);
printf("\t\tDedicatedIP: {%ws,%ws}\n",
pCfg->NlbParams.ded_ip_addr,
pCfg->NlbParams.ded_net_mask
);
}
else
{
printf("**invalid configuration**\n");
}
}
printf("\n");
delete szFriendlyName;
szFriendlyName = NULL;
return;
}
LPCWSTR bool_string(BOOL b)
{
return b ? L"true" : L"false";
}
void
display_config2(
LPCWSTR szNicGuid,
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
)
{
LPWSTR szFriendlyName = NULL;
if (g_Silent) return;
WBEMSTATUS Status;
Status = pCfg->GetFriendlyName(&szFriendlyName);
if (FAILED(Status))
{
szFriendlyName = NULL;
}
printf(
"\nNLB Configuration for %ws \"%ws\"%ws\n",
szNicGuid,
(szFriendlyName == NULL) ? L"" : szFriendlyName,
pCfg->fDHCP ? L" (DHCP)" : L""
);
// printf(" fValidNlbCfg=%d\n", pCfg->fValidNlbCfg);
// printf(" fAddDedicatedIp=%d\n", pCfg->fAddDedicatedIp);
printf(" Generation = %d\n", pCfg->Generation);
wprintf(L" NlbBound = %ws\n", bool_string(pCfg->fBound));
UINT AddrCount = pCfg->NumIpAddresses;
display_ip_info2(AddrCount, pCfg->pIpAddressInfo);
if (pCfg->fBound)
{
if (pCfg->fValidNlbCfg)
{
LPWSTR sz = NULL;
printf(" ClusterNetworkAddress = %ws/%ws\n",
pCfg->NlbParams.cl_ip_addr,
pCfg->NlbParams.cl_net_mask
);
// cluster_name
Status = pCfg->GetClusterName(&sz);
if (FAILED(Status))
{
sz = NULL;
}
else
{
printf(" ClusterName = %ws\n", sz);
delete sz;
sz = NULL;
}
// traffic_mode
{
LPCWSTR szMode = NULL;
switch(pCfg->GetTrafficMode())
{
case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST:
szMode = L"UNICAST";
break;
case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST:
szMode = L"MULTICAST";
break;
case NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST:
szMode = L"IGMPMULTICAST";
break;
default:
assert(FALSE);
szMode = L"*unknown mode*";
}
wprintf(L" TrafficMode = %ws\n", szMode);
}
// port_rules
display_port_rules(pCfg);
// host_priority
wprintf(L" HostPriority = %lu\n", pCfg->GetHostPriority());
printf(" DedicatedNetworkAddress = %ws/%ws\n",
pCfg->NlbParams.ded_ip_addr,
pCfg->NlbParams.ded_net_mask
);
// cluster_mode_on_start
DWORD ClusterModeOnStart = pCfg->GetClusterModeOnStart();
if (ClusterModeOnStart == CVY_HOST_STATE_STARTED)
{
wprintf(L" ClusterModeOnStart = %ws\n", L"true");
}
else if (ClusterModeOnStart == CVY_HOST_STATE_STOPPED)
{
wprintf(L" ClusterModeOnStart = %ws\n", L"false");
}
else // suspend
{
wprintf(L" ClusterModeOnStart = %ws\n", L"suspend");
}
// persist_suspend_on_reboot
if (pCfg->GetPersistSuspendOnReboot() == TRUE)
{
wprintf(L" PersistSuspend = %ws\n", L"true");
}
else
{
wprintf(L" PersistSuspend = %ws\n", L"false");
}
// remote_control_enabled
wprintf(L" RemoteControlEnabled = %ws\n",
bool_string(pCfg->GetRemoteControlEnabled()));
}
else
{
printf("NLB configuration is invalid\n");
}
}
printf("\n");
delete szFriendlyName;
szFriendlyName = NULL;
return;
}
void
display_port_rules(
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg
)
{
WBEMSTATUS Status;
LPWSTR *pszPortRules = NULL;
UINT NumPortRules = 0;
Status = pCfg->GetPortRules(&pszPortRules, &NumPortRules);
if (FAILED(Status))
{
wprintf(L" PortRules = *invalid*\n");
pszPortRules = NULL;
goto end;
}
if (NumPortRules)
{
wprintf(L" PortRules =\n {\n");
for (UINT u=0; u<NumPortRules; u++)
{
wprintf(
L" %ws%ws\n",
pszPortRules[u],
u==(NumPortRules-1) ? L"" : L","
);
}
wprintf(L" }\n");
}
else
{
wprintf(L" PortRules = {}\n");
}
end:
delete pszPortRules;
}
VOID
test_add_ips(LPCWSTR szNic)
//
// Go through a set of IPs on this NIC
//
{
WBEMSTATUS Status = WBEM_NO_ERROR;
UINT NumIpAddresses= 0;
NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
while(1)
{
//
// Get the current list of ip addresses
//
Status = CfgUtilGetIpAddressesAndFriendlyName(
szNic,
&NumIpAddresses,
&pIpInfo,
NULL // szFriendly name
);
if (FAILED(Status))
{
printf("Error 0x%08lx getting ip address list for %ws\n",
(UINT) Status, szNic);
pIpInfo = NULL;
goto end;
}
//
// display what we find.
//
display_ip_info(NumIpAddresses, pIpInfo);
if (pIpInfo!=NULL)
{
delete pIpInfo;
pIpInfo = NULL;
}
//
// Read the list ip address and subnet masks from the input
//
Status = read_ip_info(szNic, &NumIpAddresses, &pIpInfo);
if (FAILED(Status))
{
printf("Quitting test_add_ips\n");
break;
}
//
// Set the specified IPs
//
1 && (Status = CfgUtilSetStaticIpAddresses(
szNic,
NumIpAddresses,
pIpInfo
));
if (FAILED(Status))
{
printf("CfgUtilSetStaticIpAddresses failed with status 0x%08lx\n",
Status);
}
else
{
printf("Successfully set the specified IPs on the NIC\n");
}
}
end:
if (pIpInfo != NULL)
{
delete pIpInfo;
}
}
VOID
test_bind_nlb(LPCWSTR szNic)
{
WBEMSTATUS Status;
BOOL fBound = FALSE;
printf("\nRunning bind/unbind test for NIC %ws...\n\n", szNic);
while(1)
{
//
// Check NLB bind state
//
printf("Checking if NLB is bound...\n");
Status = CfgUtilCheckIfNlbBound(szNic, &fBound);
if (FAILED(Status))
{
printf("CfgUtilCheckIfNlbBound fails with error 0x%08lx\n", (UINT)Status);
break;
}
printf(
"NLB is %wsbound\n\n",
(fBound) ? L"" : L"NOT "
);
printf("Enter 'b' to bind, 'u' to unbind or 'q' to quit\n:");
WCHAR Temp[32] = L"";
while (wscanf(L" %1[buq]", Temp)!=1)
{
printf("Incorrect input. Try again.\n");
if (feof(stdin))
{
*Temp = 'q';
break;
}
}
if (*Temp == 'b')
{
printf("Attempting to bind NLB...\n");
fBound = TRUE;
}
else if (*Temp == 'u')
{
printf("Attempting to unbind NLB\n");
fBound = FALSE;
}
else
{
printf("Quitting\n");
break;
}
#if 1
Status = CfgUtilChangeNlbBindState(szNic, fBound);
if (FAILED(Status))
{
printf("CfgUtilChangeNlbBindState fails with error %08lx\n",
(UINT) Status);
}
else
{
printf(
"%ws completed successfully\n",
(fBound) ? L"Bind" : L"Unbind"
);
}
#endif // 0
printf("\n");
}
}
VOID
test_cfg_nlb(LPCWSTR szNic)
{
WBEMSTATUS Status;
printf("\nRunning update NLB config test for NIC %ws...\n\n", szNic);
while (1)
{
WLBS_REG_PARAMS Params;
ZeroMemory(&Params, sizeof(Params));
//
// Read NLB config
//
Status = CfgUtilGetNlbConfig(szNic, &Params);
if (FAILED(Status))
{
printf("CfgUtilGetNlbConfig fails with error 0x%08lx\n", (UINT)Status);
break;
}
printf("NLB configuration:\n");
printf(
"\tClusterIP: {%ws,%ws}\n",
Params.cl_ip_addr,
Params.cl_net_mask
);
//
// Make some modifications
//
printf("\nEnter new {cluster-ip-addr,subnet-mask} or 'q' to quit\n:");
while(1)
{
NLB_IP_ADDRESS_INFO Info;
INT i = wscanf(
L" { %15[0-9.] , %15[0-9.] }",
Info.IpAddress,
Info.SubnetMask
);
if (i!=2)
{
WCHAR Temp[100] = L"";
if ( (wscanf(L"%64ws", Temp) == 1)
&& !_wcsicmp(Temp, L"q"))
{
printf("Quitting\n");
goto end;
}
else if (feof(stdin))
{
goto end;
}
else
{
printf("Badly formed input. Try again\n");
}
}
else
{
ARRAYSTRCPY(Params.cl_ip_addr, Info.IpAddress);
ARRAYSTRCPY(Params.cl_net_mask, Info.SubnetMask);
break;
}
}
//
// Write NLB config
//
#if 1
printf("\nAttempting to update NLB configuration...\n");
Status = CfgUtilSetNlbConfig(szNic, &Params, FALSE); // FALSE==old bind
if (FAILED(Status))
{
printf("CfgUtilSetNlbConfig fails with error %08lx\n",
(UINT) Status);
}
else
{
printf("change completed successfully\n");
}
#endif // 0
printf("\n");
}
end:
return;
}
VOID
test_update(
LPCWSTR szMachineName, // NULL == don't use wmi
LPCWSTR szNicGuid
)
{
WBEMSTATUS Status;
WCHAR *pLog = NULL;
WBEMSTATUS CompletionStatus;
UINT Generation;
WMI_CONNECTION_INFO ConnInfo;
ZeroMemory(&ConnInfo, sizeof(ConnInfo));
ConnInfo.szMachine = szMachineName;
printf("\nRunning high-level update NLB config test for NIC %ws...\n\n", szNicGuid);
while(1)
{
BOOL fSetDefaults = FALSE;
UINT NumIpAddresses = 0;
NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
BOOL fUnbind = FALSE;
//
// Clean up config info
//
if (MyOldCfg.pIpAddressInfo!=NULL)
{
delete MyOldCfg.pIpAddressInfo;
}
ZeroMemory(&MyOldCfg, sizeof(MyOldCfg));
if (MyNewCfg.pIpAddressInfo!=NULL)
{
delete MyNewCfg.pIpAddressInfo;
}
ZeroMemory(&MyNewCfg, sizeof(MyNewCfg));
printf("TEST: Going to get configuration for NIC %ws\n", szNicGuid);
MyBreak(L"Break before calling GetConfiguration.\n");
if (szMachineName==NULL)
{
Status = NlbConfigurationUpdate::GetConfiguration(
szNicGuid,
&MyOldCfg
);
}
else
{
Status = NlbHostGetConfiguration(
&ConnInfo,
szNicGuid,
&MyOldCfg
);
}
if (FAILED(Status))
{
goto end;
}
display_config(szNicGuid, &MyOldCfg);
if (MyOldCfg.fBound)
{
printf("\nEnter 2 or more {cluster-ip-addr,subnet-mask} or none to unbind or 'q' to quit. The first entry is the dedicated-ip.\n");
if (!MyOldCfg.fValidNlbCfg)
{
//
// We're bound, but nlb params are bad. Set defaults.
//
fSetDefaults = TRUE;
}
}
else
{
//
// We're previously unbound. Set defaults.
//
fSetDefaults = TRUE;
printf("\nEnter 2 or more {cluster-ip-addr,subnet-mask} or 'q' to quit. The first entry is the dedicated-ip.\n");
}
while(1)
{
//
// Read the list ip address and subnet masks from the input
//
Status = read_ip_info(szNicGuid, &NumIpAddresses, &pIpInfo);
if (FAILED(Status))
{
printf("Quitting\n");
goto end;
}
if (NumIpAddresses < 2)
{
if (MyOldCfg.fBound)
{
if (NumIpAddresses == 0)
{
fUnbind = TRUE;
break;
}
else
{
printf("Wrong number of IP addresses -- enter either 0 or >= 2.\n");
}
}
else
{
printf("Wrong number of IP addresses. Enter >= 2 IP addresses.");
}
}
else
{
//
// >= 2 addresses. First one is the dip and the 2nd is the vip.
//
break;
}
if (pIpInfo != NULL)
{
delete pIpInfo;
pIpInfo = NULL;
}
}
if (fUnbind)
{
//
// We're to unbind.
//
ZeroMemory(&MyNewCfg, sizeof(MyNewCfg));
MyNewCfg.fValidNlbCfg = TRUE;
MyNewCfg.fBound = FALSE;
//
// Set the list of ip address to have present on unbind to
// be the dedicated ip address, if there is one, otherwise zero,
// in which case the adapter will be switched to DHCP after NLB
// is unbound
//
if (MyOldCfg.NlbParams.ded_ip_addr[0]!=0)
{
NLB_IP_ADDRESS_INFO *pTmpIpInfo;
pTmpIpInfo = new NLB_IP_ADDRESS_INFO;
if (pTmpIpInfo == NULL)
{
printf("TEST: allocation failure; can't add IP on unbind.\n");
}
else
{
ARRAYSTRCPY(pTmpIpInfo->IpAddress, MyOldCfg.NlbParams.ded_ip_addr);
ARRAYSTRCPY(pTmpIpInfo->SubnetMask, MyOldCfg.NlbParams.ded_net_mask);
MyNewCfg.NumIpAddresses = 1;
MyNewCfg.pIpAddressInfo = pTmpIpInfo;
}
}
}
else
{
if (fSetDefaults)
{
CfgUtilInitializeParams(&MyNewCfg.NlbParams);
MyNewCfg.fValidNlbCfg = TRUE;
MyNewCfg.fBound = TRUE;
}
else
{
MyNewCfg = MyOldCfg; // struct copy
ASSERT(MyNewCfg.fValidNlbCfg == TRUE);
ASSERT(MyNewCfg.fBound == TRUE);
}
//
// Now Add the dedicated and cluster IPs.
//
ASSERT(NumIpAddresses >= 2);
ARRAYSTRCPY(MyNewCfg.NlbParams.ded_ip_addr, pIpInfo[0].IpAddress);
ARRAYSTRCPY(MyNewCfg.NlbParams.ded_net_mask, pIpInfo[0].SubnetMask);
ARRAYSTRCPY(MyNewCfg.NlbParams.cl_ip_addr, pIpInfo[1].IpAddress);
ARRAYSTRCPY(MyNewCfg.NlbParams.cl_net_mask, pIpInfo[1].SubnetMask);
//
// If more IPs, we explicitly add the ip list, else leave it null.
//
if (NumIpAddresses > 2)
{
MyNewCfg.pIpAddressInfo = pIpInfo;
MyNewCfg.NumIpAddresses = NumIpAddresses;
}
else
{
MyNewCfg.fAddDedicatedIp = TRUE; // says to add dedicated ip.
MyNewCfg.pIpAddressInfo=NULL;
MyNewCfg.NumIpAddresses=0;
delete pIpInfo;
pIpInfo = NULL;
}
}
display_config(szNicGuid, &MyNewCfg);
printf("Going to update configuration for NIC %ws\n", szNicGuid);
MyBreak(L"Break before calling DoUpdate.\n");
if (szMachineName==NULL)
{
Status = NlbConfigurationUpdate::DoUpdate(
szNicGuid,
L"tprov.exe",
&MyNewCfg,
&Generation,
&pLog
);
}
else
{
Status = NlbHostDoUpdate(
&ConnInfo,
szNicGuid,
L"tprov.exe",
&MyNewCfg,
&Generation,
&pLog
);
}
if (pLog != NULL)
{
display_log(pLog);
delete pLog;
pLog = NULL;
}
if (Status == WBEM_S_PENDING)
{
printf(
"Waiting for pending operation %d...\n",
Generation
);
}
while (Status == WBEM_S_PENDING)
{
Sleep(1000);
if (szMachineName == NULL)
{
Status = NlbConfigurationUpdate::GetUpdateStatus(
szNicGuid,
Generation,
FALSE, // FALSE == Don't delete completion record
&CompletionStatus,
&pLog
);
}
else
{
Status = NlbHostGetUpdateStatus(
&ConnInfo,
szNicGuid,
Generation,
&CompletionStatus,
&pLog
);
}
if (pLog != NULL)
{
display_log(pLog);
delete pLog;
pLog = NULL;
}
if (!FAILED(Status))
{
Status = CompletionStatus;
}
}
printf(
"Final status of update %d is 0x%08lx\n",
Generation,
Status
);
}
end:
return;
}
VOID
display_ip_info(
IN UINT NumIpAddresses,
IN NLB_IP_ADDRESS_INFO *pIpInfo
)
{
UINT AddrCount = NumIpAddresses;
printf("\tNumIpAddresses=%d\n", AddrCount);
if (AddrCount != 0)
{
printf("\tAddress\t\tMask\n");
if (pIpInfo == NULL)
{
printf("ERROR: IpAddressInfo is NULL!\n");
goto end;
}
for (UINT u=0;u<AddrCount; u++)
{
printf(
"\t{%-15ws, %ws}\n",
pIpInfo[u].IpAddress,
pIpInfo[u].SubnetMask
);
}
}
end:
return;
}
VOID
display_ip_info2(
IN UINT NumIpAddresses,
IN NLB_IP_ADDRESS_INFO *pIpInfo
)
{
if (NumIpAddresses == 0)
{
wprintf(L" NetworkAddresses = {}\n");
}
else
{
wprintf(L" NetworkAddresses =\n {\n");
for (UINT u=0;u<NumIpAddresses; u++)
{
printf(
" %15ws/%ws%ws\n",
pIpInfo[u].IpAddress,
pIpInfo[u].SubnetMask,
(u==(NumIpAddresses-1)) ? L"" : L","
);
}
wprintf(L" }\n");
}
return;
}
WBEMSTATUS
read_ip_info(
IN LPCWSTR szNic,
OUT UINT *pNumIpAddresses,
OUT NLB_IP_ADDRESS_INFO **ppIpInfo
)
{
NLB_IP_ADDRESS_INFO *pIpInfo;
WBEMSTATUS Status = WBEM_NO_ERROR;
#define MAX_READ_IPS 10
printf("Enter zero or more {ip-address,subnet-mask} followed by '.'\n"
"(or 'q' to quit)\n:");
pIpInfo = new NLB_IP_ADDRESS_INFO[MAX_READ_IPS];
if (pIpInfo == NULL)
{
Status = WBEM_E_OUT_OF_MEMORY;
goto end;
}
for (UINT Index=0; Index<MAX_READ_IPS; Index++)
{
NLB_IP_ADDRESS_INFO *pInfo = pIpInfo+Index;
INT i = wscanf(
//L" { %15ws , %15ws }",
//L"{%15ws,%15ws}",
//L"{%ws,%ws}",
//L"{%[0-9.],%[0-9.]}",
L" { %15[0-9.] , %15[0-9.] }",
pInfo->IpAddress,
pInfo->SubnetMask
);
if (i!=2)
{
WCHAR Temp[100];
if ( (wscanf(L"%64ws", Temp) == 1)
&& !_wcsicmp(Temp, L"q"))
{
Status = WBEM_E_OUT_OF_MEMORY;
break;
}
else if (!_wcsicmp(Temp, L"."))
{
break;
}
else if (feof(stdin))
{
Status = WBEM_E_OUT_OF_MEMORY;
break;
}
else
{
printf("Badly formed input. Try again\n");
Index--;
}
}
}
*pNumIpAddresses = Index;
end:
if (FAILED(Status))
{
if (pIpInfo != NULL)
{
delete[] pIpInfo;
pIpInfo = NULL;
}
}
*ppIpInfo = pIpInfo;
return Status;
}
VOID
do_usage(VOID)
{
wprintf(
L"\n"
L"NLBCFG host [command] [options]\n"
L"\n"
L"where\n"
L"\n"
L" \"host\" is one of\n"
L" machine name\n"
L" IP address\n"
L" fully-qualified machine name\n"
L" . (implies local machine, using WMI)\n"
L" - (implies local machine, not using WMI)\n"
L"\n"
L" \"command\" is one of\n"
L" adapterlist -- list adapters compatible with NLB\n"
L" update [adapter_guid] -- bind or update NLB configuraiton\n"
L" help|h -- display help information\n"
L"\n"
L" \"command\" may also be one of the following, used for internal testing\n"
L" ipaddr [adapter_guid] -- display and change ip addresses\n"
L" nlbbind [adapter_guid] -- bind or unbind NLB\n"
L" nlbcfg [adapter_guid] -- change NLB configuration\n"
L" \n"
L" \"options\" has the form\n"
L" /u domain\\user [password | *]\n"
L"\n"
L"List of abbreviated command names and their full forms\n"
L" al adapterlist\n"
L" u update\n"
L" ? help\n"
L"\n"
L"Examples:\n"
L"\n"
L" NLBCFG machine1 adapterlist /u:mydomain\\myname *\n"
L" Displays the list of NLB-compatible adapters on the machine with\n"
L" name \"machine1\". The \"*\" indicates that the user is to be prompted\n"
L" to enter the password.\n"
L" \n"
L"\n"
L" NLBCFG 10.0.0.1 update {AD4DA14D-CAAE-42DD-97E3-5355E55247C2}\n"
L" Binds or updates the NLB configuration on a specific adapter on\n"
L" the machine with ip address \"10.0.0.1\". The adapter is identified\n"
L" by GUID \"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}\".\n"
L"\n"
L" NLBCFG . update {AD4DA14D-CAAE-42DD-97E3-5355E55247C2}\n"
L" Binds or updates the NLB configuration on a specific adapter on\n"
L" the local machine. The adapter is identified\n"
L" by GUID \"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}\".\n"
L" \n"
L" NLBCFG .\n"
L" Opens a NLB configuration shell. This shell may be used to issue\n"
L" NLB configuration commands to the local machine.\n"
L"\n"
);
}
VOID do_niclist(
LPCWSTR szSrchFriendlyName, // OPTIONAL
LPWSTR *pszFoundGuid // OPTIONAL
)
/*
szSrchFriendlyName -- if non NULL, this function searches for a matching
GUID and returns that in pszFoundGuid (which also must be NON-NULL in this
case).
Otherwise -- this function simply prints out the adapter list.
*/
{
LPWSTR *pszNics = NULL;
LPWSTR szFoundGuid = NULL;
UINT NumNics = 0;
UINT NumNlbBound = 0;
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
BOOL fDisplay = FALSE;
BOOL fDone = FALSE;
if (szSrchFriendlyName==NULL)
{
fDisplay = TRUE;
}
else
{
fDisplay = FALSE;
*pszFoundGuid = NULL;
}
Status = CfgUtilsGetNlbCompatibleNics(&pszNics, &NumNics, &NumNlbBound);
if (FAILED(Status))
{
printf("CfgUtilsGetNlbCompatibleNics returns error 0x%08lx\n",
(UINT) Status);
pszNics = NULL;
goto end;
}
if (NumNics == 0)
{
if (fDisplay)
{
printf("No compatible local adapter guids.\n");
}
}
else
{
if (fDisplay)
{
printf("Local Adapter Guids (D==DHCP N==NLB):\n");
}
for (UINT u = 0; u<NumNics && !fDone; u++)
{
LPCWSTR szNic = pszNics[u];
LPWSTR szFriendlyName = NULL;
UINT NumIpAddresses= 0;
NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
//
// Get the current list of ip addresses
//
Status = CfgUtilGetIpAddressesAndFriendlyName(
szNic,
&NumIpAddresses,
&pIpInfo,
&szFriendlyName
);
if (FAILED(Status))
{
pIpInfo = NULL;
szFriendlyName = NULL;
// wprintf(L"%ws\t<null>\t<null>\n", szNic);
wprintf(L"Error getting ip addresses for %ws\n", szNic);
}
else
{
if (fDisplay)
{
LPCWSTR szCIpAddress = L"";
LPCWSTR szCFriendlyName = L"";
LPCWSTR szNlbBound = L" ";
LPCWSTR szDHCP = L" ";
if (NumIpAddresses>0)
{
szCIpAddress = pIpInfo[0].IpAddress;
}
if (szFriendlyName != NULL)
{
szCFriendlyName = szFriendlyName;
}
//
// Get DHCP State
//
{
BOOL fDHCP = FALSE;
Status = CfgUtilGetDHCP(szNic, &fDHCP);
if (FAILED(Status))
{
printf("Error 0x%x attempting to determine DHCP state for NIC %ws",
(UINT) Status, szNic);
szDHCP = L"?";
}
else if (fDHCP)
{
szDHCP = L"D";
}
}
//
// Check if NLB bound...
//
{
BOOL fBound;
Status = CfgUtilCheckIfNlbBound(szNic, &fBound);
if (FAILED(Status))
{
fBound = FALSE;
if (Status != WBEM_E_NOT_FOUND)
{
printf("CfgUtilCheckIfNlbBound fails with error 0x%08lx\n", (UINT)Status);
szNlbBound = L"?";
}
}
if (fBound)
{
szNlbBound = L"N";
}
}
wprintf(
L"%ws %s %s %-15ws \"%ws\"\n",
szNic,
szDHCP,
szNlbBound,
szCIpAddress,
szCFriendlyName
);
}
else if (szFriendlyName != NULL)
{
if (!_wcsicmp(szSrchFriendlyName, szFriendlyName))
{
//
// Got it! Get the GUID.
//
const UINT cchLen = wcslen(szNic)+1;
szFoundGuid = new WCHAR[cchLen];
if (szFoundGuid == NULL)
{
printf("Allocation failure\n");
}
else
{
StringCchCopy(szFoundGuid, cchLen, szNic);
}
fDone = TRUE;
}
}
}
if (pIpInfo != NULL)
{
delete pIpInfo;
pIpInfo = NULL;
}
if (szFriendlyName != NULL)
{
delete szFriendlyName;
szFriendlyName = NULL;
}
}
}
end:
if (pszNics != NULL)
{
delete pszNics;
pszNics = NULL;
}
if (!fDisplay)
{
*pszFoundGuid = szFoundGuid;
}
}
VOID do_wminiclist(
LPCWSTR szSrchFriendlyName, // OPTIONAL
LPWSTR *pszFoundGuid // OPTIONAL
)
/*
szSrchFriendlyName -- if non NULL, this function searches for a matching
GUID and returns that in pszFoundGuid (which also must be NON-NULL in this
case).
Otherwise -- this function simply prints out the adapter list.
*/
{
LPWSTR szMachineName = NULL;
LPWSTR *pszNics = NULL;
LPWSTR szFoundGuid = NULL;
UINT NumNics = 0;
UINT NumNlbBound = 0;
WBEMSTATUS Status = WBEM_E_CRITICAL_ERROR;
BOOL fDisplay = FALSE;
BOOL fDone = FALSE;
LPWSTR szWmiMachineName = NULL;
LPWSTR szWmiMachineGuid = NULL;
BOOL fNlbMgrProviderInstalled = FALSE;
WMI_CONNECTION_INFO ConnInfo;
WMI_CONNECTION_INFO *pConnInfo = NULL;
ZeroMemory(&ConnInfo, sizeof(ConnInfo));
if (szSrchFriendlyName==NULL)
{
fDisplay = TRUE;
}
else
{
fDisplay = FALSE;
*pszFoundGuid = NULL;
}
ASSERT(g.fUseWmi);
if (!g.fLocalHost)
{
ConnInfo.szMachine = g.MachineName;
if (g.UserName[0])
{
ConnInfo.szUserName = g.UserName;
ConnInfo.szPassword = g.Password;
}
pConnInfo = &ConnInfo;
}
Status = NlbHostGetMachineIdentification(
pConnInfo,
&szWmiMachineName,
&szWmiMachineGuid,
&fNlbMgrProviderInstalled
);
if (FAILED(Status))
{
if (Status == E_ACCESSDENIED)
{
wprintf(L"Bad user name or password connecting to NLB on %ws.\n",
g.MachineName);
}
else
{
printf("NlbHostGetMachineIdentification returns error 0x%08lx\n",
(UINT) Status);
}
szWmiMachineName = NULL;
szWmiMachineGuid = NULL;
goto end;
}
if (!fNlbMgrProviderInstalled)
{
wprintf(L"NLB Manager is not installed on %ws.\n", g.MachineName);
goto end;
}
Status = NlbHostGetCompatibleNics(
pConnInfo,
&pszNics,
&NumNics,
&NumNlbBound
);
if (FAILED(Status))
{
if (Status == E_ACCESSDENIED)
{
wprintf(L"Bad user name or password connecting to NLB on %ws.\n",
g.MachineName);
}
else
{
printf("NlbHostGetNlbCompatibleNics returns error 0x%08lx\n",
(UINT) Status);
}
pszNics = NULL;
goto end;
}
if (NumNics == 0 && fDisplay)
{
printf("No compatible local adapter guids.\n");
}
else
{
BOOL fSavedSilent = g_Silent;
g_Silent = TRUE;
if (fDisplay)
{
if (szWmiMachineName != NULL)
{
printf("Machine Name: %ws\n", szWmiMachineName);
}
if (szWmiMachineGuid != NULL)
{
printf("Machine GUID: %ws\n", szWmiMachineGuid);
}
printf("Local Adapter Guids (D==DHCP N==NLB):\n", NumNlbBound);
}
for (UINT u=0; u<NumNics && !fDone; u++)
{
NLB_EXTENDED_CLUSTER_CONFIGURATION NlbCfg; // class
LPCWSTR szNic = pszNics[u];
Status = NlbHostGetConfiguration(
pConnInfo,
szNic,
&NlbCfg
);
if (FAILED(Status))
{
// wprintf(L"%ws\t<null>\t<null>\n", szNic);
wprintf(L"Error reading extended configuration for %ws\n", szNic);
}
else
{
UINT NumIpAddresses= 0;
NLB_IP_ADDRESS_INFO *pIpInfo = NULL;
LPWSTR szFriendlyName = NULL;
LPCWSTR szCIpAddress = L"";
LPCWSTR szCFriendlyName = L"";
LPWSTR *pszNetworkAddresses = NULL;
LPCWSTR szNlbBound = L" ";
LPCWSTR szDHCP = L" ";
if (fDisplay)
{
Status = NlbCfg.GetNetworkAddresses(
&pszNetworkAddresses,
&NumIpAddresses
);
if (FAILED(Status))
{
wprintf(L"Error extracting IP addresses for %ws\n", szNic);
NumIpAddresses = 0;
pszNetworkAddresses = NULL;
}
if (NumIpAddresses>0)
{
szCIpAddress = pszNetworkAddresses[0];
//
// NetworkAddresses are of the form "10.0.0.1/255.255.255.0"
// So we truncate this by putting a '\0' where the '/' is.
//
{
LPWSTR pSlash = wcsrchr(szCIpAddress, (int) '/');
if (pSlash != NULL)
{
*pSlash = 0;
}
}
}
if (NlbCfg.IsNlbBound())
{
szNlbBound = L"N";
}
if (NlbCfg.fDHCP)
{
szNlbBound = L"D";
}
}
Status = NlbCfg.GetFriendlyName(
&szFriendlyName
);
if (FAILED(Status))
{
szFriendlyName = NULL;
}
if (fDisplay)
{
if (szFriendlyName != NULL)
{
szCFriendlyName = szFriendlyName;
}
wprintf(
L"%ws %ws %ws %-15ws \"%ws\"\n",
szNic,
szDHCP,
szNlbBound,
szCIpAddress,
szCFriendlyName
);
}
else if (szFriendlyName != NULL)
{
if (!_wcsicmp(szSrchFriendlyName, szFriendlyName))
{
//
// Got it! Get the GUID.
//
const UINT cchLen = wcslen(szNic)+1;
szFoundGuid = new WCHAR[cchLen];
if (szFoundGuid == NULL)
{
printf("Allocation failure\n");
}
else
{
StringCchCopy(szFoundGuid, cchLen, szNic);
}
fDone = TRUE;
}
}
if (szFriendlyName != NULL)
{
delete szFriendlyName;
szFriendlyName = NULL;
}
if (pszNetworkAddresses != NULL)
{
delete pszNetworkAddresses;
pszNetworkAddresses = NULL;
}
}
}
g_Silent = fSavedSilent;
}
end:
delete szMachineName;
delete pszNics;
delete szWmiMachineName;
delete szWmiMachineGuid;
if (!fDisplay)
{
*pszFoundGuid = szFoundGuid;
}
}
VOID do_ipaddr(VOID)
{
LPWSTR szNic = NULL;
//
// Skip reading the GUID if we've got it from the command line.
//
if (!g.fGotGuid)
{
if (!read_guid(&szNic)) goto end;
ARRAYSTRCPY(g.AdapterGuid, szNic);
}
test_add_ips(szNic);
end:
if (szNic!=NULL)
{
delete szNic;
}
}
VOID do_nlbcfg(VOID)
{
LPWSTR szNic = NULL;
//
// Skip reading the GUID if we've got it from the command line.
//
if (!g.fGotGuid)
{
if (!read_guid(&szNic)) goto end;
ARRAYSTRCPY(g.AdapterGuid, szNic);
}
test_cfg_nlb(szNic);
end:
if (szNic!=NULL)
{
delete szNic;
}
}
VOID do_nlbbind(VOID)
{
LPWSTR szNic = NULL;
//
// Skip reading the GUID if we've got it from the command line.
//
if (!g.fGotGuid)
{
if (!read_guid(&szNic)) goto end;
ARRAYSTRCPY(g.AdapterGuid, szNic);
}
test_bind_nlb(szNic);
end:
if (szNic!=NULL)
{
delete szNic;
}
}
VOID do_update(VOID)
{
LPWSTR szNic = NULL;
if (!read_guid(&szNic))
{
szNic = NULL;
goto end;
}
test_update(NULL, szNic); // NULL == don't use WMI
end:
if (szNic!=NULL)
{
delete szNic;
}
}
VOID do_wmiupdate(VOID)
{
LPWSTR szNic = NULL;
LPWSTR szMachineName = NULL;
if (!read_machinename(&szMachineName))
{
szMachineName = NULL;
goto end;
}
if (!read_guid(&szNic))
{
szNic = NULL;
goto end;
}
test_update(szMachineName, szNic); // TRUE == use WMI
end:
if (szNic!=NULL)
{
delete szNic;
}
if (szMachineName!=NULL)
{
delete szMachineName;
}
}
VOID do_cleanreg(VOID)
{
printf("Unimplemented\n");
}
BOOL read_guid(
LPWSTR *pszNic
)
{
BOOL fRet = FALSE;
BOOL fValid = FALSE;
LPWSTR szNic = NULL;
#if 1
WCHAR rgTemp[256];
printf("Enter Adapter GUID: ");
do
{
// if (wscanf(L" %40[-{}a-fA-F0-9]", rgTemp)==1)
if (wscanf(L" %200ws", rgTemp) == 1)
{
fValid = valid_guid(rgTemp);
}
if (!fValid)
{
if (feof(stdin)) goto end;
printf("Incorrect format. Please re-enter Adapter Guid: ");
}
} while (!fValid);
#else
LPCWSTR rgTemp = L"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}";
#endif // 0
const UINT cchLen = wcslen(rgTemp)+1;
szNic = new WCHAR[cchLen];
if (szNic != NULL)
{
StringCchCopy(szNic, cchLen, rgTemp);
fRet = TRUE;
}
end:
*pszNic = szNic;
return fRet;
}
BOOL read_machinename(
LPWSTR *pszMachineName
)
{
BOOL fRet = FALSE;
#if 0
WCHAR rgTemp[256];
printf("\nEnter Machine Name (or '.' for local)\n:");
while (wscanf(L" %[a-zA-Z0-9._-]", rgTemp)!=1)
{
wscanf(L" %200s", rgTemp);
printf("Incorrect format. Please try again.\n");
}
if (!wcscmp(rgTemp, L"."))
{
// convert "." to ""
*rgTemp=0;
}
#else
// LPCWSTR rgTemp = L"JOSEPHJ4E";
LPCWSTR rgTemp = L"";
#endif
const UINT cchLen = wcslen(rgTemp)+1;
LPWSTR szMachineName = new WCHAR[cchLen];
if (szMachineName != NULL)
{
StringCchCopy(szMachineName, cchLen, rgTemp);
fRet = TRUE;
}
*pszMachineName = szMachineName;
return fRet;
}
void test_safearray(void)
{
SAFEARRAY *pSA;
LPCWSTR pInStrings[] =
{
L"String1",
#if 1
L"String2",
L"String3",
#endif // 0
NULL // must be last.
};
LPWSTR *pOutStrings=NULL;
UINT NumInStrings=0;
UINT NumOutStrings=0;
WBEMSTATUS Status;
//
// Find count of strings...
//
for (NumInStrings=0; pInStrings[NumInStrings]!=NULL; NumInStrings++)
{
;
}
Status = CfgUtilSafeArrayFromStrings(
pInStrings,
NumInStrings,
&pSA
);
if (FAILED(Status))
{
printf("CfgUtilSafeArrayFromStrings failed with error 0x%08lx\n", (UINT)Status);
pSA = NULL;
goto end;
}
Status = CfgUtilStringsFromSafeArray(
pSA,
&pOutStrings,
&NumOutStrings
);
if (FAILED(Status))
{
printf("CfgUtilStringsFromSafeArray failed with error 0x%08lx\n", (UINT)Status);
pOutStrings = NULL;
goto end;
}
//
// Check that they match
//
if (NumOutStrings != NumInStrings)
{
printf("ERROR: NumOutStrings != NumInStrings.\n");
goto end;
}
for (UINT u=0; u < NumInStrings; u++)
{
if (wcscmp(pInStrings[u], pOutStrings[u]))
{
printf("MISMATCH: %ws->%ws\n", pInStrings[u], pOutStrings[u]);
}
else
{
printf("MATCH: %ws->%ws\n", pInStrings[u], pOutStrings[u]);
}
}
end:
if (pSA!=NULL)
{
SafeArrayDestroy(pSA);
pSA = NULL;
}
if (pOutStrings!=NULL)
{
delete pOutStrings;
pOutStrings = NULL;
}
return;
}
VOID test_exfcfgclass(void)
/*
tests some of the methods of class NLB_EXTENDED_CLUSTER_CONFIGURATION
1. Initialize Cfg
2. Set a bunch of fields
3. display Cfg
4. Get and set a bunch of fields on new
5. display cfg
*/
{
typedef enum
{
DO_STRINGS,
DO_SAFEARRAY,
DO_STRINGPAIR,
DO_END
} TEST_COMMAND;
TEST_COMMAND cmd;
printf("Test of NLB_EXTENDED_CLUSTER_CONFIGURATION methods...\n");
UINT u1=100000L;
// while(u1--> 0)
{
// g_Silent = TRUE;
for (cmd=DO_STRINGS; cmd<DO_END; cmd=(TEST_COMMAND)((UINT)cmd + 1))
{
NLB_EXTENDED_CLUSTER_CONFIGURATION Cfg;
NLB_EXTENDED_CLUSTER_CONFIGURATION NewCfg;
WBEMSTATUS Status = WBEM_NO_ERROR;
CfgUtilInitializeParams(&Cfg.NlbParams);
CfgUtilInitializeParams(&NewCfg.NlbParams);
//
// Set a bunch of fields in Cfg
//
{
#define TPROV_NUM_ADDRESSES 2
#define TPROV_NUM_PORTS 1
LPCWSTR rgszNetworkAddresses[TPROV_NUM_ADDRESSES] = {
L"10.0.0.1/255.0.0.0",
L"10.0.0.2/255.0.0.0"
};
LPCWSTR rgszIpAddresses[TPROV_NUM_ADDRESSES] = {
L"10.0.0.1",
L"10.0.0.2"
};
LPCWSTR rgszSubnetMasks[TPROV_NUM_ADDRESSES] = {
L"255.255.255.0",
L"255.255.0.0"
};
LPCWSTR rgszPortRules[TPROV_NUM_PORTS] = {
L"ip=1.1.1.1 protocol=TCP start=80 end=288 mode=SINGLE priority=1"
};
UINT NumOldNetworkAddresses = TPROV_NUM_ADDRESSES;
UINT NumOldPortRules=TPROV_NUM_PORTS;
Cfg.fValidNlbCfg = TRUE;
Cfg.Generation = 123;
Cfg.fBound = TRUE;
if (cmd == DO_STRINGS)
{
Status = Cfg.SetNetworkAddresses(
rgszNetworkAddresses,
NumOldNetworkAddresses
);
}
else if (cmd == DO_SAFEARRAY)
{
SAFEARRAY *pOldSA = NULL;
Status = CfgUtilSafeArrayFromStrings(
rgszNetworkAddresses,
NumOldNetworkAddresses,
&pOldSA
);
if (FAILED(Status))
{
printf("ERROR: couldn't create safe array!\n");
pOldSA = NULL;
}
if (pOldSA != NULL)
{
Status = Cfg.SetNetworkAddressesSafeArray(pOldSA);
SafeArrayDestroy(pOldSA);
pOldSA = NULL;
}
}
else if (cmd == DO_STRINGPAIR)
{
Status = Cfg.SetNetworkAddresPairs(
rgszIpAddresses,
rgszSubnetMasks,
NumOldNetworkAddresses
);
}
Status = Cfg.SetPortRules(rgszPortRules, NumOldPortRules);
Cfg.SetClusterNetworkAddress(L"10.0.0.11/255.0.0.0");
Cfg.SetDedicatedNetworkAddress(L"10.0.0.1/255.0.0.0");
Cfg.SetTrafficMode(
NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST
);
Cfg.SetHostPriority(10);
Cfg.SetClusterModeOnStart( CVY_HOST_STATE_STOPPED );
Cfg.SetPersistSuspendOnReboot( FALSE );
Cfg.SetRemoteControlEnabled(TRUE);
Cfg.fValidNlbCfg = TRUE;
}
display_config2(L"<dummy nic:old>", &Cfg);
//
// Get all the fields and push it into NewCfg;
//
{
UINT NumNetworkAddresses = 0;
UINT NumPortRules=0;
LPWSTR *pszNetworkAddresses=NULL;
LPWSTR *pszIpAddresses=NULL;
LPWSTR *pszSubnetMasks=NULL;
LPWSTR *pszPortRules=NULL;
LPWSTR szClusterAddress = NULL;
LPWSTR szDedicatedAddress = NULL;
UINT Generation=0;
BOOL NlbBound=FALSE;
BOOL ValidNlbConfig=FALSE;
SAFEARRAY *pSA = NULL;
NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE
TrafficMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
/*
NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE
StartMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::START_MODE_STOPPED;
*/
DWORD StartMode = CVY_HOST_STATE_STOPPED;
BOOL PersistSuspendOnReboot = FALSE;
UINT HostPriority=0;
BOOL RemoteControlEnabled=FALSE;
//
// GET
//
Generation = Cfg.GetGeneration();
NlbBound = Cfg.IsNlbBound();
ValidNlbConfig = Cfg.IsValidNlbConfig();
if (cmd == DO_STRINGS)
{
Status = Cfg.GetNetworkAddresses(
&pszNetworkAddresses,
&NumNetworkAddresses
);
}
else if (cmd == DO_SAFEARRAY)
{
Status = Cfg.GetNetworkAddressesSafeArray(&pSA);
if (FAILED(Status))
{
pSA = NULL;
}
}
else if (cmd == DO_STRINGPAIR)
{
Status = Cfg.GetNetworkAddressPairs(
&pszIpAddresses, // free using delete
&pszSubnetMasks, // free using delete
&NumNetworkAddresses
);
}
Status = Cfg.GetPortRules(&pszPortRules, &NumPortRules);
Status = Cfg.GetClusterNetworkAddress(&szClusterAddress);
Status = Cfg.GetDedicatedNetworkAddress(&szDedicatedAddress);
TrafficMode = Cfg.GetTrafficMode();
HostPriority = Cfg.GetHostPriority();
StartMode = Cfg.GetClusterModeOnStart();
PersistSuspendOnReboot = Cfg.GetPersistSuspendOnReboot();
RemoteControlEnabled = Cfg.GetRemoteControlEnabled();
//
// SET
//
NewCfg.fValidNlbCfg = ValidNlbConfig;
NewCfg.Generation = Generation;
NewCfg.fBound = NlbBound;
if (cmd == DO_STRINGS)
{
Status = NewCfg.SetNetworkAddresses(
(LPCWSTR*) pszNetworkAddresses,
NumNetworkAddresses
);
}
else if (cmd == DO_SAFEARRAY)
{
if (pSA != NULL)
{
Status = NewCfg.SetNetworkAddressesSafeArray(pSA);
SafeArrayDestroy(pSA);
pSA = NULL;
}
}
else if (cmd == DO_STRINGPAIR)
{
Status = NewCfg.SetNetworkAddresPairs(
(LPCWSTR*) pszIpAddresses,
(LPCWSTR*) pszSubnetMasks,
NumNetworkAddresses
);
}
Status = NewCfg.SetPortRules((LPCWSTR*)pszPortRules, NumPortRules);
NewCfg.SetClusterNetworkAddress(szClusterAddress);
NewCfg.SetDedicatedNetworkAddress(szDedicatedAddress);
NewCfg.SetTrafficMode(TrafficMode);
NewCfg.SetHostPriority(HostPriority);
NewCfg.SetClusterModeOnStart(StartMode);
NewCfg.SetPersistSuspendOnReboot(PersistSuspendOnReboot);
NewCfg.SetRemoteControlEnabled(RemoteControlEnabled);
delete (pszNetworkAddresses);
delete (pszIpAddresses);
delete (pszSubnetMasks);
delete (pszPortRules);
delete (szClusterAddress);
delete (szDedicatedAddress);
}
display_config2(L"<dummy nic:new>", &NewCfg);
}
}
printf("... end test\n");
}
#if 0
AdapterList al
Update u
Quit q
Help h, ?
AdapterGuid ag
PartialUpdate pu
NetworkAddresses na
NLBBound nb
ClusterNetworkAddress cna
ClusterName cn
TrafficMode tm
PortRules pr
HostPriority hp
DedicatedNetworkAddress dna
ClusterModeOnStart cmos
RemoteControlEnabled rce
Password p
.
#endif // 0
BOOL read_password(
VOID
)
{
BOOL fRet = TRUE;
DWORD dwLen = 0;
wprintf(L"Type the password for %ws: ", g.MachineName);
fRet = GetPassword(g.Password, ARRAY_LENGTH(g.Password)-1, &dwLen);
if (!fRet)
{
printf("Error getting password!\n");
g.Password[0] = 0;
}
return fRet;
}
KEYWORD
parse_args(int argc, WCHAR* argv[])
/*++
// tprov [niclist|ipaddr|nlbcfg|nlbbind]
nlbcfg machinename|-|. [command_and_parameters] [options]
machinemame machine name
OR IP address
OR fully-qualified machine name
- Indicates not to use WMI -- call lower-level functions
directly
. Connect to local machine using wmi
command_and_parameters AdapterList
OR Update [adapter_guid]
OR Help
OR ipaddr [adapter_guid] (test)
OR nlbbinb [adapter_guid] (test)
OR nlbcfg [adapter_guid] (test)
options /u domain\user [password | *]
--*/
{
KEYWORD kw = KW_UNKNOWN;
//
// If no args, or one arg and that is /? or /help, we display help.
//
{
BOOL fDoHelp = FALSE;
if (argc<2)
{
fDoHelp = TRUE;
}
else if (argc == 2)
{
if (!_wcsicmp(argv[1], L"/?") || !wcscmp(argv[1], L"/help"))
{
fDoHelp = TRUE;
}
}
if (fDoHelp)
{
kw = KW_HELP;
goto end;
}
}
argv++; // skip past program name.
argc--;
g.fReadPassword = FALSE;
g.fGotGuid = FALSE;
g.fGotFriendlyName = FALSE;
g.fRunOnce = FALSE;
g.fUseWmi = FALSE;
g.fLocalHost = FALSE;
g.MachineName[0] = 0;
g.UserName[0] = 0;
g.Password[0] = 0;
#if 0
#define MAX_MACHINE_NAME_LENGTH 256
#define MAX_PASSWORD_LENGTH 256
#define INPUT_BUFFER_LENGTH 256
WCHAR MachineName[MAX_MACHINE_NAME_LENGTH+1];
WCHAR Password[MAX_PASSWORD_LENGTH+1];
WCHAR InputBuffer[INPUT_BUFFER_LENGTH+1];
BOOL fUseWmi;
BOOL fLocalHost;
#endif // 0
//
// Get the mandatory machine name information, which must be first.
//
{
if (!_wcsicmp(*argv, L"-"))
{
g.fUseWmi = FALSE;
}
else if (!wcscmp(*argv, L"."))
{
g.fUseWmi = TRUE;
g.fLocalHost = TRUE;
}
else
{
//
// read machine name
//
if (wcslen(*argv) >= ARRAY_LENGTH(g.MachineName))
{
wprintf(L"Machine name should be a maximum of %lu characters.\n",
ARRAY_LENGTH(g.MachineName)-1);
goto end;
}
ARRAYSTRCPY(g.MachineName, *argv);
g.fUseWmi = TRUE;
}
argv++;
argc--;
}
while (argc)
{
if (!_wcsnicmp(*argv, L"/u:", 3))
{
//
// Parse user name and password
//
LPCWSTR szUser = (*argv)+3;
wprintf(L"OPTION USER -- User==\"%ws\"\n", szUser);
UINT Len = wcslen(szUser);
if (Len == 0 || Len >= ARRAY_LENGTH(g.UserName))
{
wprintf(L"Invalid User Name: \"%ws\"\n", szUser);
goto end;
}
ARRAYSTRCPY(g.UserName, szUser);
argv++;
argc--;
if (argc)
{
//
// Get the password
//
LPCWSTR szPassword = *argv;
wprintf(L"PASSWORD=\"%ws\"\n", szPassword);
Len = wcslen(szUser);
if (Len >= ARRAY_LENGTH(g.Password))
{
wprintf(L"Pasword too long\n");
goto end;
}
if (!wcscmp(szPassword, L"*"))
{
g.fReadPassword = TRUE;
}
else
{
g.fReadPassword = FALSE;
ARRAYSTRCPY(g.Password, szPassword);
}
argv++;
argc--;
}
}
else
{
BOOL fNeedGuid = FALSE;
if (g.fRunOnce)
{
//
// We've already picked up a command to execute,
// so this is unexpected.
//
wprintf(L"Unexpected parameter \"%ws\"\n", *argv);
kw = KW_UNKNOWN;
goto end;
}
g.fRunOnce = TRUE;
kw = lookup_keyword(*argv);
switch(kw)
{
case KW_UPDATE:
case KW_IPADDR:
case KW_NLBBIND:
case KW_NLBCFG:
fNeedGuid = TRUE;
break;
case KW_ADAPTER_LIST:
case KW_HELP:
break;
default:
wprintf(L"Unexpected parameter \"%ws\"\n", *argv);
kw = KW_UNKNOWN;
goto end;
}
argv++;
argc--;
if (fNeedGuid)
{
g.fGotGuid = FALSE;
g.fGotFriendlyName = FALSE;
if (argc)
{
LPCWSTR szGuid = *argv;
//
// Get the NIC GUID or friendly name
//
UINT Len = wcslen(szGuid);
if (!Len)
{
argv++;
argc--;
continue;
}
if (
Len==NLB_GUID_LEN
&& szGuid[0] == '{'
&& szGuid[Len-1]=='}'
)
{
ARRAYSTRCPY(g.AdapterGuid, szGuid);
g.fGotGuid = TRUE;
argv++;
argc--;
}
else if (szGuid[0] == '/')
{
// Treat this as an option, not friendly name.
}
else if ( szGuid[0] != '{' // '}'
&& Len < NLB_MAX_FRIENDLY_NAME_LENGTH)
{
//
// let's assume that this is a friendly name
//
// Note -- I checked and friendly name can be
// pretty much any printible character -- including
// ! etc.
//
// SO "/....." is a valid friendly name, but we
// treat it like an option.
// Also, "{....}" is a valid friendly name, but we
// assume it's a malformed guid.
//
ARRAYSTRCPY(g.FriendlyName, szGuid);
g.fGotFriendlyName = TRUE;
argv++;
argc--;
}
else
{
wprintf(L"Expecting Adapter GUID or frienly name, not \"%ws\"\n", szGuid);
kw = KW_UNKNOWN;
goto end;
}
}
}
}
}
if (kw==KW_UNKNOWN)
{
//
// This means that no command was specified -- we invoke the
// shell
//
kw = KW_MAIN_SHELL;
}
#if 0
if (!wcscmp(argv[1], L"/uipaddr"))
if (!wcscmp(argv[1], L"ipaddr"))
{
ret = DO_IPADDR;
}
else if (!wcscmp(argv[1], L"nlbcfg"))
{
ret = DO_NLBCFG;
}
else if (!wcscmp(argv[1], L"nlbbind"))
{
ret = DO_NLBBIND;
}
else if (!wcscmp(argv[1], L"update"))
{
ret = DO_UPDATE;
}
else if (!wcscmp(argv[1], L"wmiupdate"))
{
ret = DO_WMIUPDATE;
}
else if (!wcscmp(argv[1], L"cleanreg"))
{
ret = DO_CLEANREG;
}
else
{
printf("ERROR: unknown argument\n");
}
#endif // 0
end:
return kw;
}
KEYWORD lookup_keyword(LPCWSTR szKeyword)
{
KEYWORD kw = KW_UNKNOWN;
const KEYWORD_MAP *pMap = KeywordMap;
for (; pMap->sz!=NULL; pMap++)
{
if (!_wcsicmp(szKeyword, pMap->sz))
{
// printf("Matched %ws. kw=%lu\n", pMap->sz, pMap->kw);
break;
}
}
if (pMap->sz != NULL)
{
kw = pMap->kw;
}
return kw;
}
KEYWORD read_keyword(LPCWSTR szPrompt)
/*++
If global (g.fRunOnce) is TRUE, return immediately with KW_QUIT.
Otherwise, read and identify a keyword from a set of pre-defined keywords.
--*/
{
KEYWORD kw = KW_UNKNOWN;
g.InputBuffer[0] = 0;
wprintf(L"%s", szPrompt);
//
// Skip past comment characters...
//
while (wscanf(L" %1[;]", g.InputBuffer) == 1)
{
// skip rest of this line...
WCHAR wc = 0;
do {
wc = getwchar();
} while (wc != WEOF && wc != '\n' && wc != '\r');
}
if (wscanf(L" %50[a-zA-Z.?]", g.InputBuffer) != 1)
{
//
// Invalid input, lets try to read it all into our buffer
//
if (wscanf(L"%100ws", g.InputBuffer) == 1)
{
g.InputBuffer[0] = 0;
}
goto end;
}
kw = lookup_keyword(g.InputBuffer);
end:
if (kw == KW_UNKNOWN)
{
if (feof(stdin))
{
kw = KW_QUIT;
}
else
{
//
// Kill all subsequent input
//
fseek(stdin, 0, SEEK_END);
}
}
return kw;
}
void
test_read_keyword(void)
{
KEYWORD kw;
do
{
kw = read_keyword(L"test: ");
} while (kw != KW_QUIT);
}
void parse_main(int argc, WCHAR* argv[])
{
#define szMAIN_PROMPT L"nlbcfg: "
KEYWORD kw;
kw = parse_args(argc, argv);
#if 0
wprintf(L"ARGS: MachineName = \"%ws\"\n", g.MachineName);
wprintf(L"ARGS: UserName = \"%ws\"\n", g.UserName);
wprintf(L"ARGS: Password = \"%ws\"\n", g.Password);
wprintf(L"ARGS: AdapterGuid = \"%ws\"\n", g.AdapterGuid);
wprintf(L"ARGS: fReadPassword = %lu\n", g.fReadPassword);
wprintf(L"ARGS: fUseWmi = %lu\n", g.fUseWmi);
wprintf(L"ARGS: fLocalHost = %lu\n", g.fLocalHost);
wprintf(L"ARGS: fGotGuid = %lu\n", g.fGotGuid);
wprintf(L"ARGS: KEYWORD = %lu\n", (UINT) kw);
#endif // 0
if (kw == KW_UNKNOWN || kw == KW_HELP)
{
if (kw == KW_HELP)
{
do_usage();
}
goto end;
}
//
// If necessary, read password.
//
if (g.fReadPassword)
{
if (!read_password()) goto end;
// wprintf(L"ARGS2: Password = \"%ws\"\n", g.Password);
}
if (g.fUseWmi && !g.fLocalHost)
{
//
// Let's ping the host....
//
WBEMSTATUS Status;
ULONG uIpAddress;
wprintf(L"Pinging %ws...\n", g.MachineName);
Status = NlbHostPing(g.MachineName, 2000, &uIpAddress);
if (FAILED(Status))
{
wprintf(L"Ping failed\n");
goto end;
}
else
{
wprintf(L"Ping succeeded\n");
}
}
// kw = KW_QUIT;
while (kw != KW_QUIT)
{
switch(kw)
{
case KW_MAIN_SHELL:
kw = read_keyword(szMAIN_PROMPT);
break;
case KW_IPADDR: do_ipaddr();
break;
case KW_NLBCFG: do_nlbcfg();
break;
case KW_NLBBIND: do_nlbbind();
break;
case KW_ADAPTER_LIST: kw = parse_adapter_list();
break;
case KW_UPDATE: kw = parse_update();
break;
case KW_HELP:
kw = parse_main_help();
break;
case KW_UNKNOWN:
default:
printf(
"\"%ws\" is unexpected. Type \"help\""
" for more information.\n",
g.InputBuffer
);
kw = read_keyword(szMAIN_PROMPT);
break;
}
}
end:
return;
}
KEYWORD parse_adapter_list(VOID)
/*
Report adapter list and read next command.
*/
{
KEYWORD kw = KW_UNKNOWN;
if (g.fUseWmi)
{
do_wminiclist(NULL, NULL);
}
else
{
do_niclist(NULL, NULL);
}
if (g.fRunOnce)
{
kw = KW_QUIT;
}
else
{
kw = read_keyword(szMAIN_PROMPT);
}
return kw;
}
VOID display_update_help(VOID);
VOID parse_network_addresses(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg,
BOOL *pfModified);
VOID parse_modify_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg,
BOOL *pfModified);
VOID parse_nlb_bound(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_cluster_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_cluster_name(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_traffic_mode(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_port_rules(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_host_priority(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_dedicated_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_cluster_mode_on_start(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_persist_suspend_on_reboot(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_remote_control_enabled(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
VOID parse_remote_password(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg);
void
parse_control(
BOOL fWmi,
PWMI_CONNECTION_INFO pConnInfo,
LPCWSTR szNicGuid
);
void
parse_query(
BOOL fWmi,
PWMI_CONNECTION_INFO pConnInfo,
LPCWSTR szNicGuid
);
KEYWORD parse_update(VOID)
#if 0
nlbcfg> update {guid}
Enter Adapter GUID: {guid}
NLB Configuration for Adapter xxxx xxxx:
Enter updated configuration, or type help for more information.
nlbcfg update> cna=10.0.0.1/255.255.255.0
nlbcfg update> cna=10.0.0.1/255.255.255.0
nlbcfg update> cna=10.0.0.1/255.255.255.0
nlbcfg update> .
Proposed new configuration:
.....
Enter y to confirm:
nlbcfg update> y
Going to perform update
...
....
complete
Reading configuration:
.......
Enter updated configuration or other command.
nlbcfg update>q
#endif // 0
{
BOOL fUseWmi = g.fUseWmi;
BOOL fLocal = g.fLocalHost;
LPCWSTR szNicGuid = g.AdapterGuid;
WBEMSTATUS Status;
WBEMSTATUS CompletionStatus;
UINT Generation;
WMI_CONNECTION_INFO ConnInfo;
PWMI_CONNECTION_INFO pConnInfo = NULL;
WCHAR LocalName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwLen=ARRAY_LENGTH(LocalName);
BOOL fUserSetNetworkAddresses = FALSE;
BOOL fModified = FALSE;
BOOL fCheckNewConfiguration = FALSE;
//
// Skip reading the GUID if we've got it from the command line.
//
if (!g.fGotGuid)
{
if (g.fGotFriendlyName)
{
if (!get_guid_by_friendly_name())
{
printf(
"Could not find adapter with name \"%ws\"\n",
g.FriendlyName
);
goto end;
}
}
else
{
LPWSTR szNic = NULL;
if (!read_guid(&szNic)) goto end;
ARRAYSTRCPY(g.AdapterGuid, szNic);
delete szNic;
szNic=NULL;
}
}
if (!GetComputerName(LocalName, &dwLen))
{
ARRAYSTRCPY(LocalName, L"TPROV.EXE");
}
ZeroMemory(&ConnInfo, sizeof(ConnInfo));
if (fUseWmi && !fLocal)
{
ConnInfo.szMachine = g.MachineName;
if (g.UserName[0])
{
ConnInfo.szUserName = g.UserName;
ConnInfo.szPassword = g.Password;
}
pConnInfo = &ConnInfo;
}
start:
KEYWORD kw = KW_UNKNOWN;
WCHAR *pLog = NULL;
BOOL fSetDefaults = FALSE;
BOOL fUnbind = FALSE;
BOOL fConfigInputDone = FALSE;
//
// Clean up config info
//
MyOldCfg.Clear();
MyNewCfg.Clear();
MyBreak(L"Break before calling GetConfiguration.\n");
if (!fUseWmi)
{
Status = NlbConfigurationUpdate::GetConfiguration(
szNicGuid,
&MyOldCfg
);
}
else
{
Status = NlbHostGetConfiguration(
pConnInfo,
szNicGuid,
&MyOldCfg
);
}
if (FAILED(Status))
{
wprintf(L"Could not get configuration for Adapter %ws\n", szNicGuid);
goto end;
}
display_config2(szNicGuid, &MyOldCfg);
//
// 6/2002 JosephJ Following disabled because of false failures reported
// need to investigate further.
//
if (0 && fCheckNewConfiguration)
{
//
// Check MyOldCfg against MyNewCfg -- report a problem if
// they are NOT equivalent.
//
NLBERROR nerr;
BOOL fConnectivityChange = FALSE;
nerr = MyOldCfg.AnalyzeUpdate(
&MyNewCfg,
&fConnectivityChange
);
if (nerr != NLBERR_NO_CHANGE)
{
wprintf(L"WARNING: New parameters may not match requested parameters\n");
g_nRetCode = RETCODE_NEW_CONFIG_DOESNT_MATCH;
}
else
{
wprintf(L"New parameters match requested parameters!\n");
}
}
fCheckNewConfiguration = FALSE;
if (MyOldCfg.fBound)
{
if (!MyOldCfg.fValidNlbCfg)
{
//
// We're bound, but nlb params are bad. Set defaults.
//
wprintf(L"NLB is bound, but NLB parameters appear to be bad. Setting defaults\n");
fSetDefaults = TRUE;
}
}
else
{
//
// We're previously unbound. Set defaults.
//
fSetDefaults = TRUE;
}
//
// We setup the new configuration based on the old configuration, but
// additionally (if required) set the NLB params to default values,
// whether-or-not NLB is bound.
//
MyNewCfg.Update(&MyOldCfg); // copy
//
// We zap the network address list.
// We'll pick up the old ones IF the user hasn't changed them.
//
MyNewCfg.SetNetworkAddresses(NULL, 0);
if (fSetDefaults)
{
CfgUtilInitializeParams(&MyNewCfg.NlbParams);
MyNewCfg.fValidNlbCfg = TRUE;
}
else
{
ASSERT(MyNewCfg.fBound == TRUE);
}
ASSERT(MyNewCfg.fValidNlbCfg == TRUE);
wprintf(L"Enter updated configuration, or type help for more information.\n");
//
// We accept changes to the configuration in a loop.
// We get out of the loop when the user types "." or "quit"
//
do
{
#define szUPDATE_PROMPT L"nlbcfg update> "
kw = read_keyword(szUPDATE_PROMPT);
switch(kw)
{
case KW_QUIT:
printf("quit\n");
fConfigInputDone = TRUE;
break;
case KW_DOT:
printf("END OF CONFIG INPUT\n");
fConfigInputDone = TRUE;
break;
case KW_HELP:
display_update_help();
break;
case KW_NETWORK_ADDRESSES:
fModified = FALSE;
parse_network_addresses(&MyNewCfg, &fModified);
if (fModified)
{
fUserSetNetworkAddresses = TRUE;
}
break;
case KW_MODIFY_NETWORK_ADDRESS:
fModified = FALSE;
parse_modify_network_address(&MyNewCfg, &fModified);
if (fModified)
{
fUserSetNetworkAddresses = TRUE;
}
break;
#if 0
case KW_PARTIAL_UPDATE:
printf("partial update\n");
break;
#endif // 0
case KW_NLB_BOUND:
parse_nlb_bound(&MyNewCfg);
break;
case KW_CLUSTER_NETWORK_ADDRESS:
parse_cluster_network_address(&MyNewCfg);
break;
case KW_CLUSTER_NAME:
parse_cluster_name(&MyNewCfg);
break;
case KW_TRAFFIC_MODE:
parse_traffic_mode(&MyNewCfg);
break;
case KW_PORT_RULES:
parse_port_rules(&MyNewCfg);
break;
case KW_HOST_PRIORITY:
parse_host_priority(&MyNewCfg);
break;
case KW_DEDICATED_NETWORK_ADDRESS:
parse_dedicated_network_address(&MyNewCfg);
break;
case KW_CLUSTER_MODE_ON_START:
parse_cluster_mode_on_start(&MyNewCfg);
break;
case KW_PERSIST_SUSPEND_ON_REBOOT:
parse_persist_suspend_on_reboot(&MyNewCfg);
break;
case KW_REMOTE_CONTROL_ENABLED:
parse_remote_control_enabled(&MyNewCfg);
break;
case KW_PASSWORD:
parse_remote_password(&MyNewCfg);
break;
case KW_LIST:
display_config2(szNicGuid, &MyNewCfg);
break;
case KW_CONTROL:
parse_control(fUseWmi, pConnInfo, szNicGuid); // actually do op
break;
case KW_QUERY:
parse_query(fUseWmi, pConnInfo, szNicGuid);
break;
case KW_UNKNOWN:
default:
printf("unknown command \"%ws\"!\n", g.InputBuffer);
break;
}
} while (!fConfigInputDone);
if (kw == KW_QUIT)
{
goto end;
}
if (MyOldCfg.IsNlbBound() == MyNewCfg.IsNlbBound())
{
if (!fUserSetNetworkAddresses)
{
LPWSTR *pszOldAddresses = NULL;
UINT NumOldAddresses = 0;
ASSERT(MyNewCfg.NumIpAddresses == 0);
Status = MyOldCfg.GetNetworkAddresses(
&pszOldAddresses,
&NumOldAddresses
);
if (FAILED(Status))
{
wprintf(L"Error extracting old IP addresses\n");
NumOldAddresses = 0;
pszOldAddresses = NULL;
}
MyNewCfg.SetNetworkAddresses(
(LPCWSTR*)pszOldAddresses,
NumOldAddresses
);
delete pszOldAddresses;
pszOldAddresses=NULL;
}
}
else if (!MyNewCfg.IsNlbBound())
{
//
// We're to unbind.
//
if (!fUserSetNetworkAddresses)
{
//
// Set the list of ip address to have present on unbind to
// be the dedicated ip address, if there is one, otherwise zero,
// in which case the adapter will be switched to DHCP after NLB
// is unbound
//
ASSERT(MyNewCfg.NumIpAddresses == 0);
if (MyOldCfg.NlbParams.ded_ip_addr[0]!=0)
{
NLB_IP_ADDRESS_INFO *pIpInfo;
pIpInfo = new NLB_IP_ADDRESS_INFO;
if (pIpInfo == NULL)
{
printf("TEST: allocation failure; can't add IP on unbind.\n");
}
else
{
ARRAYSTRCPY(pIpInfo->IpAddress, MyOldCfg.NlbParams.ded_ip_addr);
ARRAYSTRCPY(pIpInfo->SubnetMask, MyOldCfg.NlbParams.ded_net_mask);
MyNewCfg.NumIpAddresses = 1;
MyNewCfg.pIpAddressInfo = pIpInfo;
}
}
}
}
display_config2(szNicGuid, &MyNewCfg);
kw = read_keyword(L"Begin update? ");
while (kw!=KW_YES && kw!=KW_NO)
{
kw = read_keyword(L"Enter yes or no: ");
}
if (kw == KW_NO) goto start; // TODO: get rid of these gotos!
MyBreak(L"Break before calling DoUpdate.\n");
//
// Set the AddDedicateIp and AddClusterIps fields.
//
MyNewCfg.fAddDedicatedIp = TRUE;
MyNewCfg.fAddClusterIps = TRUE;
if (!fUseWmi)
{
Status = NlbConfigurationUpdate::DoUpdate(
szNicGuid,
LocalName,
&MyNewCfg,
&Generation,
&pLog
);
}
else
{
Status = NlbHostDoUpdate(
pConnInfo,
szNicGuid,
LocalName,
&MyNewCfg,
&Generation,
&pLog
);
}
if (pLog != NULL)
{
display_log(pLog);
delete pLog;
pLog = NULL;
}
if (Status == WBEM_S_PENDING)
{
printf(
"Waiting for pending operation %d...\n",
Generation
);
}
while (Status == WBEM_S_PENDING)
{
Sleep(1000);
if (!fUseWmi)
{
Status = NlbConfigurationUpdate::GetUpdateStatus(
szNicGuid,
Generation,
FALSE, // FALSE == Don't delete completion record
&CompletionStatus,
&pLog
);
}
else
{
Status = NlbHostGetUpdateStatus(
pConnInfo,
szNicGuid,
Generation,
&CompletionStatus,
&pLog
);
}
if (pLog != NULL)
{
display_log(pLog);
delete pLog;
pLog = NULL;
}
if (!FAILED(Status))
{
Status = CompletionStatus;
}
}
printf(
"Final status of update %d is 0x%08lx\n",
Generation,
Status
);
if (FAILED(Status))
{
g_nRetCode = RETCODE_UPDATE_FAILED;
}
else
{
fCheckNewConfiguration = TRUE;
g_nRetCode = RETCODE_NO_ERROR;
}
goto start;
end:
if (g.fRunOnce)
{
kw = KW_QUIT;
}
else
{
kw = read_keyword(szMAIN_PROMPT);
}
return kw;
}
VOID display_update_help(VOID)
{
wprintf(L"\nNlbCfg update-specific commands\n");
wprintf(L" Help\n");
wprintf(L" ; <comment text>\n");
wprintf(L" na|NetworkAddresses = <list of IP addresses and subnets>\n");
wprintf(L" nb|NlbBound = true | false\n");
wprintf(L" cn|ClusterName = <cluster domain name>\n");
wprintf(L" tm|TrafficMode = UNICAST | MULTICAST | IGMPMULTICAST\n");
wprintf(L" pr|PortRules = <list of port rules>\n");
wprintf(L" hp|HostPriority = <host priority>\n");
wprintf(L" ps|PersistSuspend = true | false\n");
wprintf(L" dna|DedicatedNetworkAddress = <dedicated IP address and subnet>\n");
wprintf(L" cmos|ClusterModeOnStart = true | false\n");
wprintf(L" rce|RemoteControlEnabled = true | false\n");
wprintf(L" p|Password = <remote control password>\n");
wprintf(L" cl|Control start(st) | stop(sp) | drainstop(ds) | suspend(su) | resume(re) | query(qu) \n");
wprintf(L" cl|Control [vip=<ip-addr>] port=<port> enable(en) | disable(di) | drain(dn) | query(qu) \n");
wprintf(L" Query -- queries for cluster members\n");
wprintf(L" q|Quit\n");
wprintf(L"\nExample:\n");
wprintf(L" ; this is a comment\n");
wprintf(L" NlbBound = true\n");
wprintf(L" nb = true (equivalent to the above)\n");
wprintf(L" NetworkAddresses = {10.1.0.6/255.255.0.0, 10.1.0.66/255.255.0.0}\n");
wprintf(L" ClusterNetworkAddress = 10.1.0.66/255.255.0.0\n");
wprintf(L" ClusterName = cluster.domain.com\n");
wprintf(L" TrafficMode = UNICAST\n");
wprintf(L" PortRules =\n");
wprintf(L" {\n");
wprintf(L" ip=10.0.1.1 protocol=TCP start=80 end=288 mode=SINGLE priority=1\n");
wprintf(L" }\n");
wprintf(L" HostPriority = 1\n");
wprintf(L" DedicatedNetworkAddress = 10.1.0.6/255.255.0.0\n");
wprintf(L" ClusterModeOnStart = true\n");
wprintf(L" RemoteControlEnabled = false\n");
wprintf(L" cl start\n");
wprintf(L" cl vip=10.1.1.1 port=80 drain\n");
wprintf(L" cl port=80 disable\n");
wprintf(L" Query\n");
}
VOID parse_network_addresses(
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg,
BOOL *pfModified
)
#if 0
Input format (the NetworkAddresses part has already been read)
NetworkAddresses = {
10.0.0.1/255.0.0.0,
10.0.0.2/255.0.0.0,
10.0.0.3/255.0.0.0,
}
#endif // 0
{
#define MAX_INPUT_ADDRESSES 20
LPWSTR *pszAddresses = NULL;
UINT Count=0;
*pfModified = FALSE;
#define MY_MAX_NETWORK_ADDRESS_LENGTH \
(WLBS_MAX_CL_IP_ADDR + 1 + WLBS_MAX_CL_NET_MASK)
pszAddresses = CfgUtilsAllocateStringArray(
MAX_INPUT_ADDRESSES,
MY_MAX_NETWORK_ADDRESS_LENGTH
);
if (pszAddresses == NULL)
{
wprintf(L"Memory Allocation Failure.\n");
goto end;
}
//
// Look for = and open brace
//
if (wscanf(L" = %1[{]", g.InputBuffer) != 1) // -}-
{
goto end_bad_input;
}
//
// Read a list of comma-separated ipaddresses/subnets
//
BOOL fDone = FALSE;
while (!fDone && Count<MAX_INPUT_ADDRESSES)
{
LPWSTR szAddr = pszAddresses[Count];
WCHAR IpAddress[32];
WCHAR SubnetMask[32];
BOOL fGotAddr = FALSE;
INT i = wscanf(
L" %15[0-9.] / %15[0-9.] ",
IpAddress,
SubnetMask
);
if (i==2)
{
StringCchPrintf(
szAddr,
MY_MAX_NETWORK_ADDRESS_LENGTH,
L"%ws/%ws", IpAddress, SubnetMask);
fGotAddr = TRUE;
Count++;
}
else if (i==1)
{
wprintf(L"Missing subnet mask.\n");
goto end;
}
//
// Look for , or open-brace
//
i = wscanf(L" %1[},]", g.InputBuffer); // -{-
if (i == 1)
{
if (*g.InputBuffer == '}') // -{-
{
fDone = TRUE;
}
else if (!fGotAddr || *g.InputBuffer != ',')
{
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
}
else
{
goto end_bad_input;
}
}
//
// We've got zero or more ip addresses. Let's set em.
//
WBEMSTATUS Status;
Status = pCfg->SetNetworkAddresses((LPCWSTR*)pszAddresses, Count);
if (FAILED(Status))
{
wprintf(L"Error 0x%08lx copying network addresses\n", (UINT) Status);
}
else
{
*pfModified = TRUE;
}
#if 0
UINT AddrCount = pCfg->NumIpAddresses;
display_ip_info2(AddrCount, pCfg->pIpAddressInfo);
#endif // 0
goto end;
end_bad_input:
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
// fall through...
end:
delete pszAddresses;
pszAddresses = NULL;
return;
}
VOID parse_modify_network_address(
NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg,
BOOL *pfModified
)
#if 0
Input format (the ModifyNetworkAddress part has already been read)
ModifyNetworkAddress = 10.0.0.1, 10.0.0.2/255.0.0.0
ModifyNetworkAddress = -, 10.0.0.2/255.0.0.0
ModifyNetworkAddress = 10.0.0.1, -
ModifyNetworkAddress = -,-
#endif // 0
{
WCHAR rgOldAddr[32];
WCHAR rgNewIpAddr[66];
WCHAR rgNewSubnetMask[32];
LPCWSTR szOldAddr = NULL;
LPCWSTR szNewIpAddr = NULL;
*pfModified = FALSE;
*rgOldAddr = 0;
*rgNewIpAddr = 0;
*rgNewSubnetMask = 0;
INT i = wscanf(L" = %15[0-9.-] ,", rgOldAddr);
if (i!=1)
{
goto end_bad_input;
}
i = wscanf(L" %15[0-9.-]", rgNewIpAddr);
if (i!=1)
{
goto end_bad_input;
}
if (_wcsicmp(rgNewIpAddr, L"-"))
{
i = wscanf(L" / %15[0-9.]", rgNewSubnetMask);
if (i!=1)
{
wprintf(L"Missing subnet mask.\n");
goto end_bad_input;
}
szNewIpAddr = rgNewIpAddr;
}
if (_wcsicmp(rgOldAddr, L"-"))
{
szOldAddr = rgOldAddr;
}
WBEMSTATUS Status;
#if 1
Status = pCfg->ModifyNetworkAddress(szOldAddr, szNewIpAddr,rgNewSubnetMask);
#else
{
BOOL fRet;
NlbIpAddressList IpList;
fRet = IpList.Set(pCfg->NumIpAddresses, pCfg->pIpAddressInfo, 0);
if (fRet)
{
fRet = IpList.Modify(szOldAddr, szNewIpAddr, rgNewSubnetMask);
}
if (fRet)
{
pCfg->SetNetworkAddressesRaw(NULL,0);
IpList.Extract(REF pCfg->NumIpAddresses, REF pCfg->pIpAddressInfo);
Status = WBEM_NO_ERROR;
}
else
{
Status = WBEM_E_CRITICAL_ERROR;
}
}
#endif
if (Status != WBEM_NO_ERROR)
{
printf("pCfg->ModifyNetworkAddress returns error 0x%08lx\n",
Status);
}
*pfModified = TRUE;
goto end;
end_bad_input:
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(
L"Invalid format. Format: [-|ip-address],[-|network-address]\n");
// fall through...
end:
return;
}
VOID parse_nlb_bound(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
/*
NlbBound = true | false
*/
{
BOOL NlbBound = FALSE;
INT i = wscanf(
L" = %15s",
g.InputBuffer
);
if (i==1)
{
if (!_wcsicmp(g.InputBuffer, L"true") || !_wcsicmp(g.InputBuffer, L"t"))
{
NlbBound = TRUE;
}
else if (!_wcsicmp(g.InputBuffer, L"false") || !_wcsicmp(g.InputBuffer, L"f"))
{
NlbBound = FALSE;
}
else
{
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
pCfg->SetNlbBound(NlbBound);
// wprintf(L"DBG: NlbBound=%lu\n", pCfg->IsNlbBound());
end:
return;
}
VOID parse_cluster_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
/*++
ClusterNetworkAddress = 10.0.0.0/255.255.255.255
--*/
{
WCHAR IpAddress[32];
WCHAR SubnetMask[32];
INT i = wscanf(
L" = %15[0-9.] / %15[0-9.]",
IpAddress,
SubnetMask
);
if (i==2)
{
StringCbPrintf(
g.InputBuffer,
sizeof(g.InputBuffer),
L"%ws/%ws", IpAddress, SubnetMask);
pCfg->SetClusterNetworkAddress(g.InputBuffer);
}
else if (i==1)
{
wprintf(L"Missing subnet mask.\n");
goto end;
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
// DBG
{
LPWSTR szAddr = NULL;
WBEMSTATUS Status;
Status = pCfg->GetClusterNetworkAddress(&szAddr);
if (FAILED(Status))
{
printf("Couldn't get address!\n");
}
else
{
// wprintf(L"DBG: CNA=%ws\n", szAddr);
delete szAddr;
}
}
end:
return;
}
VOID parse_cluster_name(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
/*++
ClusterName = cluster.microsoft.com
--*/
{
INT i = wscanf(
L" = %ws",
g.InputBuffer
);
if (i==1)
{
pCfg->SetClusterName(g.InputBuffer);
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
// DBG
{
LPWSTR szName = NULL;
WBEMSTATUS Status;
Status = pCfg->GetClusterName(&szName);
if (FAILED(Status))
{
printf("Couldn't get name!\n");
}
else
{
// wprintf(L"DBG: CN=%ws\n", szName);
delete szName;
}
}
end:
return;
}
VOID parse_traffic_mode(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
/*
TrafficMode = UNICAST | MULTICAST | IGMPMULTICAST
*/
{
NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE TrafficMode;
INT i = wscanf(
L" = %ws",
g.InputBuffer
);
if (i==1)
{
if (!_wcsicmp(g.InputBuffer, L"UNICAST") || !_wcsicmp(g.InputBuffer, L"U"))
{
TrafficMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_UNICAST;
}
else if (!_wcsicmp(g.InputBuffer, L"MULTICAST") || !_wcsicmp(g.InputBuffer, L"M"))
{
TrafficMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_MULTICAST;
}
else if (!_wcsicmp(g.InputBuffer, L"IGMPMULTICAST") || !_wcsicmp(g.InputBuffer, L"I"))
{
TrafficMode=NLB_EXTENDED_CLUSTER_CONFIGURATION::TRAFFIC_MODE_IGMPMULTICAST;
}
else
{
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
pCfg->SetTrafficMode(TrafficMode);
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
// DBG
{
TrafficMode = pCfg->GetTrafficMode();
// wprintf(L"DBG: TrafficMode=%ld\n", (UINT) TrafficMode);
}
end:
return;
}
VOID parse_port_rules(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
{
#define MAX_PORT_RULES 32
LPWSTR *pszPortRules = NULL;
UINT Count=0;
#define MY_MAX_PORT_RULE_LENGTH 128
pszPortRules = CfgUtilsAllocateStringArray(
MAX_PORT_RULES,
MY_MAX_PORT_RULE_LENGTH
);
if (pszPortRules == NULL)
{
wprintf(L"Memory Allocation Failure.\n");
goto end;
}
//
// Look for = and open brace
//
if (wscanf(L" = %1[{]", g.InputBuffer) != 1) // -}-
{
goto end_bad_input;
}
//
// Read a list of comma-separated list of port rules
//
BOOL fDone = FALSE;
while (!fDone && Count<MAX_PORT_RULES)
{
LPWSTR szPR = pszPortRules[Count];
BOOL fGotPR = FALSE;
int i;
//
// We suck up everything until the first , or close-brace.
//
if (wscanf(L" %128[^},]", g.InputBuffer) == 1) // -{-
{
BOOL fRet = FALSE;
WLBS_PORT_RULE Pr;
// printf("DBG: Got \"%ws\"\n", g.InputBuffer);
fRet = CfgUtilsSetPortRuleString(
g.InputBuffer,
&Pr
);
if (fRet == FALSE)
{
wprintf(L"Invalid port rule: \"%ws\"\n", g.InputBuffer);
goto end;
}
Count++;
fGotPR = TRUE;
g.InputBuffer[MY_MAX_PORT_RULE_LENGTH] = 0;
StringCchCopy(szPR, MY_MAX_PORT_RULE_LENGTH, g.InputBuffer);
}
//
// Look for , or open-brace
//
i = wscanf(L" %1[},]", g.InputBuffer); // -{-
if (i == 1)
{
if (*g.InputBuffer == '}') // -{-
{
fDone = TRUE;
}
else if (!fGotPR || *g.InputBuffer != ',')
{
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
}
else
{
goto end_bad_input;
}
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
//
// We've got zero or more port rules. Let's set em.
//
WBEMSTATUS Status;
Status = pCfg->SetPortRules((LPCWSTR*)pszPortRules, Count);
if (FAILED(Status))
{
wprintf(L"Error 0x%08lx copying port rules\n", (UINT) Status);
}
// display_port_rules(pCfg);
goto end;
end_bad_input:
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
// fall through...
end:
delete pszPortRules;
pszPortRules = NULL;
return;
}
VOID parse_host_priority(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
/*
HostPriority=10
*/
{
UINT Pri = 0;
INT i = wscanf(
L" = %lu",
&Pri
);
if (i==1)
{
pCfg->SetHostPriority(Pri);
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
// wprintf(L"DBG: HostPriority=%lu\n", pCfg->GetHostPriority());
end:
return;
}
VOID parse_dedicated_network_address(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
/*++
DedicatedNetworkAddress = 10.0.0.0/255.255.255.255
--*/
{
WCHAR IpAddress[32];
WCHAR SubnetMask[32];
INT i = wscanf(
L" = %15[0-9.] / %15[0-9.]",
IpAddress,
SubnetMask
);
if (i==2)
{
StringCbPrintf(
g.InputBuffer,
sizeof(g.InputBuffer),
L"%ws/%ws", IpAddress, SubnetMask);
pCfg->SetDedicatedNetworkAddress(g.InputBuffer);
}
else if (i==1)
{
wprintf(L"Missing subnet mask.\n");
goto end;
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
// DBG
{
LPWSTR szAddr = NULL;
WBEMSTATUS Status;
Status = pCfg->GetDedicatedNetworkAddress(&szAddr);
if (FAILED(Status))
{
printf("Couldn't get address!\n");
}
else
{
// wprintf(L"DBG: DNA=%ws\n", szAddr);
delete szAddr;
}
}
end:
return;
}
VOID parse_cluster_mode_on_start(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
{
INT i = wscanf(
L" = %15s",
g.InputBuffer
);
if (i==1)
{
DWORD sm;
if (!_wcsicmp(g.InputBuffer, L"true") || !_wcsicmp(g.InputBuffer, L"t"))
{
sm = CVY_HOST_STATE_STARTED;
}
else if (!_wcsicmp(g.InputBuffer, L"false") || !_wcsicmp(g.InputBuffer, L"f"))
{
sm = CVY_HOST_STATE_STOPPED;
}
else if (!_wcsicmp(g.InputBuffer, L"suspend") || !_wcsicmp(g.InputBuffer, L"s"))
{
sm = CVY_HOST_STATE_SUSPENDED;
}
else
{
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
pCfg->SetClusterModeOnStart(sm);
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
// wprintf(L"DBG: CMOS=%lu\n", (INT) pCfg->GetClusterModeOnStart());
end:
return;
}
VOID parse_persist_suspend_on_reboot(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
{
INT i = wscanf(
L" = %15s",
g.InputBuffer
);
if (i==1)
{
BOOL ps;
if (!_wcsicmp(g.InputBuffer, L"true") || !_wcsicmp(g.InputBuffer, L"t"))
{
ps = TRUE;
}
else if (!_wcsicmp(g.InputBuffer, L"false") || !_wcsicmp(g.InputBuffer, L"f"))
{
ps = FALSE;
}
else
{
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
pCfg->SetPersistSuspendOnReboot(ps);
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
// wprintf(L"DBG: CMOS=%lu\n", (INT) pCfg->GetClusterModeOnStart());
end:
return;
}
VOID parse_remote_control_enabled(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
/*
RemoteControlEnabled = true | false
*/
{
BOOL Enabled = FALSE;
INT i = wscanf(
L" = %15s",
g.InputBuffer
);
if (i==1)
{
if (!_wcsicmp(g.InputBuffer, L"true") || !_wcsicmp(g.InputBuffer, L"t"))
{
Enabled = TRUE;
}
else if (!_wcsicmp(g.InputBuffer, L"false") || !_wcsicmp(g.InputBuffer, L"f"))
{
Enabled = FALSE;
}
else
{
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
pCfg->SetRemoteControlEnabled(Enabled);
// wprintf(L"DBG: RemoteControlEnabled=%lu\n", pCfg->GetRemoteControlEnabled());
end:
return;
}
VOID parse_remote_password(NLB_EXTENDED_CLUSTER_CONFIGURATION *pCfg)
/*
Password=blah
*/
{
INT i = wscanf(
L" = %ws",
g.InputBuffer
);
if (i==1)
{
// TODO: This is unsuppoted.
// pCfg->SetPassword(g.InputBuffer);
wprintf(L"Unimplemented\n");
goto end;
}
else
{
if (wscanf(L"% 100ws", g.InputBuffer)!=1)
{
*g.InputBuffer = 0;
}
wprintf(L"\"%ws\" unexpected.\n", g.InputBuffer);
goto end;
}
if (!pCfg->IsNlbBound())
{
wprintf(L"Assuming NLB needs to be bound.\n");
pCfg->SetNlbBound(TRUE);
}
end:
return;
}
KEYWORD parse_main_help(VOID)
{
printf("Commands:\n");
printf(" AdapterList|al - displays a list of NLB-compatible adapters\n");
printf(" Update|u <guid> - displays current configuration for the specified\n"
" adapter and then accepts commands to update\n"
" that configuration\n");
printf(" Help|h|? - displays this help message\n");
printf(" Quit|q - exits the NLB configuration shell\n");
KEYWORD kw;
if (g.fRunOnce)
{
kw = KW_QUIT;
}
else
{
kw = read_keyword(szMAIN_PROMPT);
}
return kw;
}
#if 0
parse_wmiupdate()
{
COMMAND_TYPE Cmd;
read_guid();
// get config and display it
// read new config from stdin
do
{
Cmd = read_keyword();
switch(Cmd)
{
NETWORK_ADDRESSES:
DOT: // end of config change description
ADAPTER_LIST:
HELP:
fQuit=TRUE;
greak;
}
} while (!fQuit)
return Cmd;
}
#endif // 0
BOOL valid_guid(LPCWSTR szGuid)
{
UINT Len = wcslen(szGuid);
if (
Len!=NLB_GUID_LEN
|| szGuid[0] != '{'
|| szGuid[Len-1]!='}'
)
{
return FALSE;
}
return TRUE;
}
BOOL
GetPassword(
PWSTR szBuffer,
DWORD dwLength,
DWORD *pdwLengthReturn
)
/*
Reads the password from stdin, WITHOUT echoing the password chars to
stdiout.
JosephJ 6/3/01
Taken verbatim from \nt\ds\ds\src\util\csvds.
It was one of the dirs that showed up when I did an index search
for "Type the password for", which is what the "net use" command
prompts when asking for a password.
Works like a charm.
*/
{
#define CR 0xD
#define BACKSPACE 0x8
#define NULLC '\0'
#define NEWLINE '\n'
WCHAR ch;
PWSTR pszBufCur = szBuffer;
DWORD c;
int err;
DWORD mode;
//
// make space for NULL terminator
//
dwLength -= 1;
*pdwLengthReturn = 0;
if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
&mode)) {
return FALSE;
}
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
(~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode);
while (TRUE) {
err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
&ch,
1,
&c,
0);
if (!err || c != 1)
ch = 0xffff;
if ((ch == CR) || (ch == 0xffff)) // end of line
break;
if (ch == BACKSPACE) { // back up one or two
//
// IF pszBufCur == buf then the next two lines are a no op.
// Because the user has basically backspaced back to the start
//
if (pszBufCur != szBuffer) {
pszBufCur--;
(*pdwLengthReturn)--;
}
}
else {
*pszBufCur = ch;
if (*pdwLengthReturn < dwLength)
pszBufCur++ ; // don't overflow buf
(*pdwLengthReturn)++; // always increment pdwLengthReturn
}
}
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
//
// NULL terminate the string
//
*pszBufCur = NULLC;
putchar(NEWLINE);
return((*pdwLengthReturn <= dwLength) ? TRUE : FALSE);
}
VOID
test_port_rule_string(VOID)
{
LPCWSTR RuleStrings[] =
{
L"",
L" \t \n ",
L"n=v",
L" \t \n n=v",
L" \t \n n \t \n = \t \n v",
L"na=v1 nb=v2 nc=v3",
L"\t na \t = \t v1 \t nb \t \n =\t \n v2 \t \n nc \t = \n v3 ",
#if 1
L"ip=1.1.1.1 protocol=TCP start=80 end=288 mode=SINGLE"
L" priority=1",
L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
L" affinity=SINGLE load=80",
L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
L" affinity=NONE load=80",
L"ip=1.1.1.1 protocol=UDP start=80 end=288 mode=MULTIPLE"
L" affinity=CLASSC",
L"ip=1.1.1.1 protocol=BOTH start=80 end=288 mode=DISABLED",
#endif // 0
NULL // Must be last
};
for (LPCWSTR *ppRs = RuleStrings; *ppRs!=NULL; ppRs++)
{
LPCWSTR szRule = *ppRs;
WCHAR szGenString[NLB_MAX_PORT_STRING_SIZE];
printf("ORIG: %ws\n", szRule);
WLBS_PORT_RULE Pr;
BOOL fRet;
fRet = CfgUtilsSetPortRuleString(
szRule,
&Pr
);
if (fRet == FALSE)
{
printf("CfgUtilsSetPortRuleString returned FAILURE.\n");
continue;
}
fRet = CfgUtilsGetPortRuleString(
&Pr,
szGenString
);
if (fRet == FALSE)
{
printf("CfgUtilsGetPortRuleString returned FAILURE.\n");
continue;
}
printf("GEN: %ws\n", szGenString);
}
}
BOOL
get_guid_by_friendly_name(VOID)
{
LPWSTR szGuid = NULL;
BOOL fRet = FALSE;
szGuid = L"{AD4DA14D-CAAE-42DD-97E3-5355E55247C2}";
if (g.fUseWmi)
{
do_wminiclist(g.FriendlyName, &szGuid);
}
else
{
do_niclist(g.FriendlyName, &szGuid);
}
if (szGuid != NULL)
{
ARRAYSTRCPY(g.AdapterGuid, szGuid);
// printf("FR=\"%ws\"; Guid=%ws\n", g.FriendlyName, g.AdapterGuid);
delete szGuid; szGuid = NULL;
fRet = TRUE;
}
return fRet;
}
void test_vectors(void)
{
vector<_bstr_t> v1;
vector<_bstr_t> v2;
vector<_bstr_t> *pv3 = new vector<_bstr_t>;
WCHAR szBlah[10];
ARRAYSTRCPY(szBlah, L"blah");
v1.push_back(szBlah);
v1.push_back(szBlah);
*pv3 = v1;
v2 = *pv3;
delete pv3;
for (int i = 0; i< v1.size(); i++)
{
LPCWSTR sz1 = v1[i];
LPCWSTR sz2 = v2[i];
printf("v1[%d] = 0x%p(%ws); v2[i] = 0x%p(%ws)\n", i, sz1, sz1, sz2, sz2);
v2[i] = L"";
sz2 = v2[i];
printf("v1[%d] = 0x%p(%ws); v2[i] = 0x%p(%ws)\n", i, sz1, sz1, sz2, sz2);
}
}
typedef ULONG ENGINEHANDLE;
class CInterfaceSpec
{
public:
_bstr_t bstrGuid;
};
void test_maps(void)
{
ENGINEHANDLE ehA = 1;
ENGINEHANDLE ehB = 3;
CInterfaceSpec iSpecA;
CInterfaceSpec iSpecB;
iSpecA.bstrGuid = _bstr_t(L"ISpecA");
iSpecB.bstrGuid = _bstr_t(L"ISpecB");
map< ENGINEHANDLE, CInterfaceSpec* > mymap;
mymap[ehA] = &iSpecA;
mymap[ehB] = &iSpecB;
printf("eh=%lu, &iSpec=0x%p, mymap[eh]=%p\n", ehA, &iSpecA, mymap[ehA]);
printf("eh=%lu, &iSpec=0x%p, mymap[eh]=%p\n", ehB, &iSpecB, mymap[ehB]);
map< ENGINEHANDLE, CInterfaceSpec* >::iterator iter;
for( iter = mymap.begin();
iter != mymap.end();
++iter)
{
CInterfaceSpec *pISpec = (*iter).second;
ENGINEHANDLE eh = (*iter).first;
printf("ITER: (eh=%lu, pISpec=%p, guid=%ws)\n", eh, pISpec,
LPCWSTR(pISpec->bstrGuid));
}
}
void test_validate_network_address(void)
{
WCHAR rgAddress[256];
UINT uIpAddress=0;
UINT uSubnet=0;
UINT uDefaultSubnet=0;
WBEMSTATUS wStat;
printf("Enter network address; 'q' to quit\n:");
while (wscanf(L" %64ws", rgAddress)==1)
{
if (!_wcsicmp(rgAddress, L"q"))
{
break;
}
wStat = CfgUtilsValidateNetworkAddress(
rgAddress,
&uIpAddress,
&uSubnet,
&uDefaultSubnet
);
if (wStat != WBEM_NO_ERROR)
{
printf("CfgUtilsValidateNetworkAddress returns error 0x%08lx\n",
wStat);
}
else
{
LPBYTE szI= (LPBYTE)&uIpAddress;
LPBYTE szS= (LPBYTE)&uSubnet;
LPBYTE szD= (LPBYTE)&uDefaultSubnet;
printf(
"\"%ws\" ->"
"(%lu.%lu.%lu.%lu, %lu.%lu.%lu.%lu, %lu.%lu.%lu.%lu)\n",
rgAddress,
szI[0], szI[1], szI[2], szI[3],
szS[0], szS[1], szS[2], szS[3],
szD[0], szD[1], szD[2], szD[3]
);
}
printf(":");
}
}
VOID MapStatusToDescription(DWORD Status, _bstr_t &szDescr)
{
struct STATUS_DESCR_MAP
{
DWORD Status;
LPCSTR Description;
}
StatusDescrMap[] =
{
{WLBS_ALREADY, "WLBS_ALREADY"},
{WLBS_BAD_PARAMS, "WLBS_BAD_PARAMS"},
{WLBS_NOT_FOUND, "WLBS_NOT_FOUND"},
{WLBS_STOPPED, "WLBS_STOPPED"},
{WLBS_SUSPENDED, "WLBS_SUSPENDED"},
{WLBS_CONVERGING, "WLBS_CONVERGING"},
{WLBS_CONVERGED, "WLBS_CONVERGED (Non-Default)"},
{WLBS_DEFAULT, "WLBS_DEFAULT (Converged as Default)"},
{WLBS_BAD_PASSW, "WLBS_BAD_PASSW"},
{WLBS_DRAINING, "WLBS_DRAINING"},
{WLBS_DRAIN_STOP, "WLBS_DRAIN_STOP"},
{WLBS_DISCONNECTED, "WLBS_DISCONNECTED"},
{WLBS_FAILURE, "WLBS_FAILURE"},
{WLBS_REFUSED, "WLBS_REFUSED"},
{WLBS_OK, "WLBS_OK"},
{WLBS_IO_ERROR, "WLBS_IO_ERROR"},
{NLB_PORT_RULE_NOT_FOUND, "PORT_RULE_NOT_FOUND"},
{NLB_PORT_RULE_ENABLED, "PORT_RULE_ENABLED"},
{NLB_PORT_RULE_DISABLED, "PORT_RULE_DISABLED"},
{NLB_PORT_RULE_DRAINING, "PORT_RULE_DRAINING"}
};
for (int i=0; i<sizeof(StatusDescrMap) /sizeof(StatusDescrMap[0]); i++)
{
if (StatusDescrMap[i].Status == Status)
{
szDescr = StatusDescrMap[i].Description;
return;
}
}
//
// Default
//
{
char temp[256];
StringCbPrintfA(temp, sizeof(temp), "Unknown (%lu)",Status);
szDescr = temp;
}
return ;
}
void
parse_control(
BOOL fWmi,
PWMI_CONNECTION_INFO pConnInfo,
LPCWSTR szNicGuid
)
//
// control [ip=x] port=y enable/disable/drain/query/nop
// control start/stop/query/nop
//
{
KEYWORD kw;
BOOL fGotPort = FALSE;
BOOL fGotIp = FALSE;
BOOL fGotCmd = FALSE;
KEYWORD kwCmd = KW_UNKNOWN;
WCHAR rgIp[32];
LPCWSTR szIp = NULL;
DWORD dwPort = 0;
WBEMSTATUS Status = WBEM_NO_ERROR;
DWORD dwOperationStatus = 0;
DWORD dwClusterOrPortStatus = 0;
DWORD dwHostMap = 0;
DWORD *pdwPort = NULL;
*rgIp=0;
while (!fGotCmd)
{
kw = read_keyword(L"");
switch(kw)
{
case KW_START:
case KW_STOP:
case KW_DRAIN:
case KW_DRAIN_STOP:
case KW_SUSPEND:
case KW_RESUME:
case KW_ENABLE:
case KW_DISABLE:
case KW_QUERY:
fGotCmd = TRUE;
kwCmd = kw;
break;
case KW_VIP:
// Look for "=<ip address>", eg. "= 10.0.0.1"
if (fGotIp)
{
wprintf(L"control: duplicate IP specification\n");
goto end; // parse error
}
if (wscanf(L" = %15[0-9.]", rgIp) != 1)
{
wprintf(L"control: bad ip specification\n");
goto end;
}
szIp = rgIp;
fGotIp = TRUE;
// printf("GOT IP \"%ws\"\n", rgIp);
break;
case KW_PORT:
// Look for "=<port>", eg. " = 80"
if (fGotPort)
{
wprintf(L"control: duplicate port specification\n");
goto end; // parse error
}
if (wscanf(L" = %lu", &dwPort) != 1)
{
wprintf(L"control: bad port specification\n");
goto end;
}
pdwPort = &dwPort;
fGotPort = TRUE;
// printf("GOT PORT %lu\n", dwPort);
break;
default: // parse error
printf("control: unknown argument\n");
goto end;
}
}
//
// Param checking
//
switch(kwCmd)
{
case KW_START: // following are adapter-wide
case KW_STOP:
case KW_DRAIN_STOP:
case KW_SUSPEND:
case KW_RESUME:
if (fGotIp || fGotPort)
{
wprintf(L"control: unexpected port or ip\n");
goto end; // parse error;
}
break;
case KW_ENABLE: // following are port-specific
case KW_DISABLE:
case KW_DRAIN:
if (!fGotPort)
{
wprintf(L"control: missing port\n");
goto end; // parse error;
}
if (!fGotIp)
{
wprintf(L"Assuming \"All Vip\", ie. Vip=255.255.255.255\n");
szIp = L"255.255.255.255"; // Default - "All Vip"
}
break;
case KW_QUERY:
{
if (fGotIp && ! fGotPort)
{
wprintf(L"control: missing port\n");
goto end; // parse error;
}
if (!fGotIp && fGotPort)
{
wprintf(L"Assuming \"All Vip\", ie. Vip=255.255.255.255\n");
szIp = L"255.255.255.255"; // default -- all vip
}
}
break;
default:
// we don't expect to get here.
goto end;
}
//
// Actually execute
//
{
WLBS_OPERATION_CODES Op = WLBS_START;
switch(kwCmd)
{
case KW_START:
// wprintf(L"DO START\n");
Op = WLBS_START;
break;
case KW_STOP:
Op = WLBS_STOP;
// wprintf(L"DO STOP\n");
break;
case KW_DRAIN_STOP:
Op = WLBS_DRAIN;
// wprintf(L"DO DRAIN STOP\n");
break;
case KW_SUSPEND:
Op = WLBS_SUSPEND;
// wprintf(L"DO SUSPEND\n");
break;
case KW_RESUME:
// wprintf(L"DO RESUME\n");
Op = WLBS_RESUME;
break;
case KW_ENABLE:
// wprintf(L"DO ENABLE\n");
Op = WLBS_PORT_ENABLE;
break;
case KW_DISABLE:
// wprintf(L"DO DISABLE\n");
Op = WLBS_PORT_DISABLE;
break;
case KW_DRAIN:
Op = WLBS_PORT_DRAIN;
// wprintf(L"DO DRAIN\n");
break;
case KW_QUERY:
if (fGotPort)
{
Op = WLBS_QUERY_PORT_STATE;
}
else
{
Op = WLBS_QUERY;
}
// wprintf(L"DO QUERY\n");
break;
default:
goto end; // don't expect to get here.
} // end switch
#define NEWSTUFF 1
#if NEWSTUFF
if (fWmi)
{
Status = NlbHostControlCluster(
pConnInfo,
szNicGuid,
szIp,
pdwPort,
Op,
&dwOperationStatus,
&dwClusterOrPortStatus,
&dwHostMap
);
}
else //
{
UINT uIp = 0;
if (!_wcsicmp(szIp, L"255.255.255.255")) // lazy eval
{
uIp = 0xffffffff; // all-vip
}
else
{
Status = CfgUtilsValidateNetworkAddress(szIp, &uIp, NULL, NULL);
if (FAILED(Status))
{
printf("control: invalid Ip address\n");
goto end;
}
}
switch(Op)
{
case WLBS_START:
case WLBS_STOP:
case WLBS_DRAIN:
case WLBS_SUSPEND:
case WLBS_RESUME:
CfgUtilControlCluster( szNicGuid, Op, 0, 0, NULL, &dwOperationStatus );
CfgUtilControlCluster( szNicGuid, WLBS_QUERY, 0, 0, &dwHostMap, &dwClusterOrPortStatus );
break;
case WLBS_PORT_ENABLE:
case WLBS_PORT_DISABLE:
case WLBS_PORT_DRAIN:
CfgUtilControlCluster( szNicGuid, Op, uIp, dwPort, NULL, &dwOperationStatus );
CfgUtilControlCluster( szNicGuid, WLBS_QUERY_PORT_STATE, uIp, dwPort, NULL, &dwClusterOrPortStatus );
break;
case WLBS_QUERY:
CfgUtilControlCluster( szNicGuid, WLBS_QUERY, 0, 0, &dwHostMap, &dwClusterOrPortStatus );
dwOperationStatus = WLBS_OK;
break;
case WLBS_QUERY_PORT_STATE:
default:
CfgUtilControlCluster( szNicGuid, WLBS_QUERY_PORT_STATE, uIp, dwPort, NULL, &dwClusterOrPortStatus );
dwOperationStatus = WLBS_OK;
break;
}
}
#endif // NEWSTUFF
if (FAILED(Status))
{
printf("ControlCluster returns failure 0x%08lx\n", Status);
}
else
{
_bstr_t szOperationStatusDescr, szClusterOrPortStatusStr;
MapStatusToDescription(dwOperationStatus, szOperationStatusDescr);
MapStatusToDescription(dwClusterOrPortStatus, szClusterOrPortStatusStr);
printf("ControlCluster returns Operation Status = %s\n",(LPCSTR)szOperationStatusDescr);
printf(" Cluster/Port State = %s\n",(LPCSTR)szClusterOrPortStatusStr);
printf(" Host Map = 0x%08lx\n",dwHostMap);
}
}
end:
return;
}
void
parse_query(
BOOL fWmi,
PWMI_CONNECTION_INFO pConnInfo,
LPCWSTR szNicGuid
)
//
// query -- list the members in the cluster
//
{
DWORD dwNumMembers = 0;
NLB_CLUSTER_MEMBER_INFO *pMembers = NULL;
WBEMSTATUS Status = WBEM_NO_ERROR;
if (fWmi)
{
Status = NlbHostGetClusterMembers(
pConnInfo,
szNicGuid,
&dwNumMembers,
&pMembers
);
}
else // !fWmi
{
Status = CfgUtilGetClusterMembers(
szNicGuid,
&dwNumMembers,
&pMembers
);
}
if (FAILED(Status))
{
printf("QueryCluster returns failure 0x%08lx\n", Status);
}
else
{
wprintf(L"HostID DedicatedIP HostName\n");
wprintf(L"-----------------------------------------------------\n");
DWORD dwHost = 0;
for (; dwHost < dwNumMembers; dwHost++)
{
wprintf(L"%-11d %-16ls %ls\n",
pMembers[dwHost].HostId,
(pMembers[dwHost].DedicatedIpAddress == NULL) ? L"" : pMembers[dwHost].DedicatedIpAddress,
(pMembers[dwHost].HostName == NULL) ? L"" : pMembers[dwHost].HostName
);
}
if (pMembers != NULL)
{
delete [] pMembers;
pMembers = NULL;
}
}
}
void display_nlbipaddresslist(
const NlbIpAddressList &IpList
)
{
BOOL fRet;
NlbIpAddressList IpListCopy;
NLB_IP_ADDRESS_INFO *pInfo=NULL;
UINT uNum=0;
fRet = IpListCopy.Copy(IpList);
if (!fRet) goto end;
IpListCopy.Extract(REF uNum, REF pInfo);
display_ip_info2(uNum, pInfo);
end:
delete pInfo;
}
void test_nlbipaddresslist(void)
{
BOOL fRet;
NlbIpAddressList IpList;
typedef struct
{
LPCWSTR szOld;
LPCWSTR szNew;
LPCWSTR szMask;
} MY_MODIFY_INFO;
#define MY_TERMINAL ((LPCWSTR) 0x1)
MY_MODIFY_INFO rgModInfo[] =
{
{NULL},
{NULL,L"1",L"11"},
{NULL,L"2",L"22"},
{NULL,L"3",L"33"},
{L"3",L"2", L"23"},
{L"2",L"1", L"13"},
{L"1",L"4", L"44"},
{L"1",L"4", L"44"},
{L"1",L"1", L"111"},
{L"3"},
{L"2"},
{L"1"},
{MY_TERMINAL} // must be last.
};
#if 0
for (MY_MODIFY_INFO *pModInfo = rgModInfo;
pModInfo->szOld != MY_TERMINAL;
pModInfo++
)
{
wprintf(
L"TRIAL: Old=\"%ws\" New=\"%ws\" Mask=\"%ws\"\n",
(pModInfo->szOld==NULL) ? L"<null>" : pModInfo->szOld,
(pModInfo->szNew==NULL) ? L"<null>" : pModInfo->szNew,
(pModInfo->szMask==NULL) ? L"<null>" : pModInfo->szMask
);
fRet = IpList.Modify(
pModInfo->szOld,
pModInfo->szNew,
pModInfo->szMask
);
display_nlbipaddresslist(IpList);
}
#endif // 0
NLB_IP_ADDRESS_INFO rgOrigInfo[] = {
{L"1", L"11"},
{L"2", L"22"},
{L"3", L"33"}
};
NLB_IP_ADDRESS_INFO rgNewInfo[] = {
{L"5", L"155"},
{L"4", L"144"},
{L"3", L"133"},
{L"2", L"122"},
};
#define ASIZE(_array) (sizeof(_array)/sizeof(_array[0]))
fRet = IpList.Set(ASIZE(rgOrigInfo), rgOrigInfo, 0);
// fRet = IpList.Set(0, NULL, 0);
if (!fRet)
{
goto end;
}
printf("Original List (before Apply):\n");
display_nlbipaddresslist(IpList);
fRet = IpList.Apply(ASIZE(rgNewInfo), rgNewInfo);
// fRet = IpList.Apply(0, NULL);
if (!fRet)
{
goto end;
}
printf("\nNew List (after Apply):\n");
display_nlbipaddresslist(IpList);
end:
if (fRet)
{
printf("display_nlbipaddresslist Test PASSED\n");
}
else
{
printf("display_nlbipaddresslist Test FAILED\n");
}
}
void test_ioctl_alignment(void)
{
//
// Just to check out the offsets of the following structures and sub-structures
// in the debugger to make sure that the packet versions are 8-byte aligned
//
//
IOCTL_CVY_BUF icb;
IOCTL_COMMON_OPTIONS ico;
IOCTL_REMOTE_OPTIONS iro;
IOCTL_REMOTE_HDR irh;
IOCTL_LOCAL_OPTIONS ilo;
IOCTL_LOCAL_HDR ilh;
NLB_OPTIONS_PORT_RULE_STATE prs;
NLB_OPTIONS_PACKET_FILTER pf;
}
void test_local_logger(void)
{
CLocalLogger logger;
LPCWSTR szLog = NULL;
//
// Warning: should match IDS_PROCESSING_UPDATE from ..\nlbmprov.h
//
#define IDS_PROCESING_UPDATE 200
for (UINT u = 1; u<50; u++)
{
logger.Log(IDS_PROCESING_UPDATE, u, L"test_local_logger");
}
szLog = logger.GetStringSafe();
wprintf(szLog);
}
void test_encrypt_memory(void)
{
BOOL fRet;
//
// JosephJ 4/10/02 Verified the following passwords as well...
// LPCWSTR szPwd = L"asdfasdfasdfasdfasdf asdf asdf asdfasdfasdf af a";
// LPCWSTR szPwd = L"1";
LPCWSTR szPwd = L"";
//
// LPCWSTR szPwd = L"password";
WCHAR rgEncPwd[64];
// WCHAR rgEncPwd[256]; (use with longest pwd above)
WCHAR rgDecPwd[32];
// WCHAR rgDecPwd[128]; (use with longest pwd above)
fRet = CfgUtilEncryptPassword(szPwd, ASIZE(rgEncPwd), rgEncPwd);
if (!fRet)
{
printf("CfgUtilEncryptPassword failed.\n");
goto end;
}
else
{
wprintf(L"Encrypted pwd = \"%ws\"\n", rgEncPwd);
}
fRet = CfgUtilDecryptPassword(rgEncPwd, ASIZE(rgDecPwd), rgDecPwd);
if (!fRet)
{
printf("CfgUtilDecryptPassword failed.\n");
goto end;
}
else
{
wprintf(L"Decrypted pwd = \"%ws\"\n", rgDecPwd);
}
end:
return;
}