/*++ 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= 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;uIpAddress, 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\t\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\t\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", &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"", &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" ; \n"); wprintf(L" na|NetworkAddresses = \n"); wprintf(L" nb|NlbBound = true | false\n"); wprintf(L" cn|ClusterName = \n"); wprintf(L" tm|TrafficMode = UNICAST | MULTICAST | IGMPMULTICAST\n"); wprintf(L" pr|PortRules = \n"); wprintf(L" hp|HostPriority = \n"); wprintf(L" ps|PersistSuspend = true | false\n"); wprintf(L" dna|DedicatedNetworkAddress = \n"); wprintf(L" cmos|ClusterModeOnStart = true | false\n"); wprintf(L" rce|RemoteControlEnabled = true | false\n"); wprintf(L" p|Password = \n"); wprintf(L" cl|Control start(st) | stop(sp) | drainstop(ds) | suspend(su) | resume(re) | query(qu) \n"); wprintf(L" cl|Control [vip=] 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 && CountSetNetworkAddresses((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 && CountIsNlbBound()) { 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 - 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", 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 "=", 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"" : pModInfo->szOld, (pModInfo->szNew==NULL) ? L"" : pModInfo->szNew, (pModInfo->szMask==NULL) ? L"" : 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; }