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.

2961 lines
102 KiB

  1. /*++
  2. Copyright(c) 1998,99 Microsoft Corporation
  3. Module Name:
  4. control.cpp
  5. Abstract:
  6. Windows Load Balancing Service (WLBS)
  7. Command-line utility
  8. Author:
  9. kyrilf
  10. ramkrish (Post Win2K)
  11. --*/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <conio.h>
  15. #include <stdlib.h>
  16. #include <process.h>
  17. #include <time.h>
  18. #include <locale.h>
  19. #include <winsock2.h>
  20. #include <ws2tcpip.h>
  21. #include <tchar.h>
  22. #include <shlwapi.h>
  23. #include <strsafe.h>
  24. #include "debug.h"
  25. #define WLBSAPI_INTERNAL_ONLY
  26. #define BACKWARD_COMPATIBILITY
  27. #define CVY_MAX_ADAPTERS 16
  28. #include "wlbsutil.h"
  29. #include "wlbsctrl.h"
  30. #include "wlbsconfig.h"
  31. #include "wlbsparm.h"
  32. #include "wlbsiocl.h"
  33. #include "wlbsip.h"
  34. #define CLIENT
  35. #include "log_msgs.h"
  36. /* CONSTANTS */
  37. #define CVY_OK 1
  38. #define CVY_ERROR_USAGE -1
  39. #define CVY_ERROR_REGISTRY -2
  40. #define CVY_ERROR_SYSTEM -3
  41. #define CVY_ERROR_USER -4
  42. #define CVY_BUF_SIZE 4096
  43. #define CVY_MAX_EVENTS 10
  44. #define CVY_MAX_INSERTS 10
  45. #define CVY_ALL_CLUSTERS 0xffffffff
  46. #define CVY_ALL_HOSTS 0xffffffff
  47. #define CVY_LOCAL_CLUSTER 0
  48. #define CVY_LOCAL_HOST WLBS_LOCAL_HOST
  49. typedef enum {
  50. mcastipaddress,
  51. iptomcastip,
  52. masksrcmac,
  53. iptomacenable,
  54. netmonalivemsgs
  55. } WLBS_REG_KEYS;
  56. typedef enum {
  57. query,
  58. suspend,
  59. resume,
  60. __start,
  61. stop,
  62. drainstop,
  63. enable,
  64. disable,
  65. drain,
  66. reload,
  67. display,
  68. ip2mac,
  69. help,
  70. registry,
  71. filter,
  72. params,
  73. queryport,
  74. bdateam,
  75. invalid
  76. } WLBS_COMMANDS;
  77. static HANDLE file_hdl = NULL;
  78. static HANDLE ConsoleHdl;
  79. static BYTE g_buffer [CVY_BUF_SIZE];
  80. static WCHAR message [CVY_BUF_SIZE];
  81. static WCHAR ConsoleBuf [CVY_BUF_SIZE];
  82. static CHAR g_szConsoleBuf [sizeof(WCHAR)*CVY_BUF_SIZE]; // Used when I/O is redirected to something other than the console buffer.
  83. static WCHAR wbuf [CVY_STR_SIZE];
  84. static WCHAR psw_buf [CVY_STR_SIZE];
  85. static WCHAR g_PathName [MAX_PATH + 1];
  86. static BOOL g_fOutToConsole = TRUE;
  87. VOID WConsole(const wchar_t *fmt, ...)
  88. {
  89. va_list arglist;
  90. DWORD res1, res2;
  91. // Form a string out of the arguments
  92. va_start(arglist, fmt);
  93. (VOID) StringCchVPrintf(ConsoleBuf, ASIZECCH(ConsoleBuf), fmt, arglist);
  94. va_end(arglist);
  95. // Attempt WriteConsole, if it fails, do a wprintf
  96. if (g_fOutToConsole)
  97. {
  98. if (!WriteConsole(ConsoleHdl, ConsoleBuf, lstrlenW(ConsoleBuf), &res1, &res2))
  99. {
  100. wprintf(ConsoleBuf);
  101. }
  102. }
  103. else
  104. {
  105. //
  106. // Don't output anything if we fail to convert using the current code page.
  107. //
  108. if (WideCharToMultiByte( GetConsoleOutputCP(), 0, ConsoleBuf, -1, g_szConsoleBuf, ASIZECB(g_szConsoleBuf), NULL, NULL) != 0)
  109. {
  110. printf(g_szConsoleBuf);
  111. }
  112. }
  113. return;
  114. }
  115. VOID Message_print (DWORD id, ...) {
  116. va_list arglist;
  117. DWORD error;
  118. va_start(arglist, id);
  119. if (FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, id, 0, message, CVY_BUF_SIZE, & arglist) == 0) {
  120. error = GetLastError();
  121. //
  122. // Can't localize this because we've got a failure trying
  123. // to display a localized message..
  124. //
  125. WConsole(L"Could not print error message due to: ");
  126. if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, message, CVY_BUF_SIZE, NULL) == 0)
  127. WConsole(L"%d\n", error);
  128. else
  129. WConsole(L"\n %ls\n", message);
  130. } else
  131. WConsole(L"%ls", message);
  132. }
  133. VOID Error_print (BOOL sock) {
  134. DWORD error;
  135. if (sock) {
  136. error = WSAGetLastError();
  137. switch (error) {
  138. case WSAENETUNREACH:
  139. Message_print(IDS_CTR_WS_NUNREACH);
  140. break;
  141. case WSAETIMEDOUT:
  142. Message_print(IDS_CTR_WS_TIMEOUT);
  143. break;
  144. case WSAHOST_NOT_FOUND:
  145. Message_print(IDS_CTR_WS_NOAUTH);
  146. break;
  147. case WSATRY_AGAIN:
  148. Message_print(IDS_CTR_WS_NODNS);
  149. break;
  150. case WSAENETDOWN:
  151. Message_print(IDS_CTR_WS_NETFAIL);
  152. break;
  153. case WSAEHOSTUNREACH:
  154. Message_print(IDS_CTR_WS_HUNREACH);
  155. break;
  156. case WSAENETRESET:
  157. Message_print(IDS_CTR_WS_RESET);
  158. break;
  159. default:
  160. Message_print(IDS_CTR_ER_CODE, error);
  161. break;
  162. }
  163. } else {
  164. error = GetLastError();
  165. if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, message, CVY_BUF_SIZE, NULL) == 0)
  166. Message_print(IDS_CTR_ER_CODE, error);
  167. else
  168. WConsole(L"%ls\n", message);
  169. }
  170. }
  171. INT Report (WLBS_COMMANDS command, BOOLEAN condensed, ULONG ret_code, ULONG param1, ULONG param2,
  172. ULONG query_state, ULONG host_id, ULONG host_map) {
  173. ULONG i;
  174. BOOL first;
  175. switch (command) {
  176. case reload:
  177. if (ret_code == WLBS_BAD_PARAMS) {
  178. Message_print(IDS_CTR_BAD_PARAMS);
  179. return CVY_ERROR_USER;
  180. } else
  181. Message_print(IDS_CTR_RELOADED);
  182. break;
  183. case resume:
  184. if (condensed)
  185. if (ret_code == WLBS_ALREADY)
  186. Message_print(IDS_CTR_RESUMED_C_A);
  187. else
  188. Message_print(IDS_CTR_RESUMED_C);
  189. else
  190. if (ret_code == WLBS_ALREADY)
  191. Message_print(IDS_CTR_RESUMED_A);
  192. else
  193. Message_print(IDS_CTR_RESUMED);
  194. break;
  195. case suspend:
  196. if (condensed)
  197. if (ret_code == WLBS_ALREADY)
  198. Message_print(IDS_CTR_SUSPENDED_C_A);
  199. else {
  200. if (ret_code == WLBS_STOPPED)
  201. Message_print(IDS_CTR_FROM_START_C);
  202. Message_print(IDS_CTR_SUSPENDED_C);
  203. }
  204. else
  205. if (ret_code == WLBS_ALREADY)
  206. Message_print(IDS_CTR_SUSPENDED_A);
  207. else {
  208. if (ret_code == WLBS_STOPPED)
  209. Message_print(IDS_CTR_FROM_START);
  210. Message_print(IDS_CTR_SUSPENDED);
  211. }
  212. break;
  213. case __start:
  214. if (ret_code == WLBS_SUSPENDED) {
  215. if (condensed)
  216. Message_print(IDS_CTR_SUSPENDED_C);
  217. else
  218. Message_print(IDS_CTR_SUSPENDED);
  219. return CVY_ERROR_USER;
  220. } else if (ret_code == WLBS_BAD_PARAMS) {
  221. if (condensed)
  222. Message_print(IDS_CTR_BAD_PARAMS_C);
  223. else
  224. Message_print(IDS_CTR_BAD_PARAMS);
  225. return CVY_ERROR_USER;
  226. } else {
  227. if (condensed)
  228. if (ret_code == WLBS_ALREADY)
  229. Message_print(IDS_CTR_STARTED_C_A);
  230. else {
  231. if (ret_code == WLBS_DRAIN_STOP)
  232. Message_print(IDS_CTR_FROM_DRAIN_C);
  233. Message_print(IDS_CTR_STARTED_C);
  234. }
  235. else
  236. if (ret_code == WLBS_ALREADY)
  237. Message_print(IDS_CTR_STARTED_A);
  238. else {
  239. if (ret_code == WLBS_DRAIN_STOP)
  240. Message_print(IDS_CTR_FROM_DRAIN);
  241. Message_print(IDS_CTR_STARTED);
  242. }
  243. }
  244. break;
  245. case stop:
  246. if (ret_code == WLBS_SUSPENDED) {
  247. if (condensed)
  248. Message_print(IDS_CTR_SUSPENDED_C);
  249. else
  250. Message_print(IDS_CTR_SUSPENDED);
  251. return CVY_ERROR_USER;
  252. }else {
  253. if (condensed)
  254. if (ret_code == WLBS_ALREADY)
  255. Message_print(IDS_CTR_STOPPED_C_A);
  256. else
  257. Message_print(IDS_CTR_STOPPED_C);
  258. else
  259. if (ret_code == WLBS_ALREADY)
  260. Message_print(IDS_CTR_STOPPED_A);
  261. else
  262. Message_print(IDS_CTR_STOPPED);
  263. }
  264. break;
  265. case drainstop:
  266. if (ret_code == WLBS_SUSPENDED) {
  267. if (condensed)
  268. Message_print(IDS_CTR_SUSPENDED_C);
  269. else
  270. Message_print(IDS_CTR_SUSPENDED);
  271. return CVY_ERROR_USER;
  272. } else {
  273. if (condensed)
  274. if (ret_code == WLBS_STOPPED)
  275. Message_print(IDS_CTR_STOPPED_C);
  276. else if (ret_code == WLBS_ALREADY)
  277. Message_print(IDS_CTR_DRAINED_C_A);
  278. else
  279. Message_print(IDS_CTR_DRAINED_C);
  280. else
  281. if (ret_code == WLBS_STOPPED)
  282. Message_print(IDS_CTR_STOPPED);
  283. else if (ret_code == WLBS_ALREADY)
  284. Message_print(IDS_CTR_DRAINED_A);
  285. else
  286. Message_print(IDS_CTR_DRAINED);
  287. }
  288. break;
  289. case enable:
  290. case disable:
  291. case drain:
  292. if (ret_code == WLBS_SUSPENDED) {
  293. if (condensed)
  294. Message_print(IDS_CTR_SUSPENDED_C);
  295. else
  296. Message_print(IDS_CTR_SUSPENDED);
  297. return CVY_ERROR_USER;
  298. } else if (ret_code == WLBS_STOPPED) {
  299. if (condensed)
  300. Message_print(IDS_CTR_RLS_ST_C);
  301. else
  302. Message_print(IDS_CTR_RLS_ST);
  303. return CVY_ERROR_USER;
  304. } else if (ret_code == WLBS_NOT_FOUND) {
  305. if (param2 == IOCTL_ALL_PORTS)
  306. {
  307. if (param1 == IOCTL_ALL_VIPS) {
  308. if (condensed)
  309. Message_print(IDS_CTR_RLS_NORULES_C);
  310. else
  311. Message_print(IDS_CTR_RLS_NORULES);
  312. }
  313. else if (param1 == IpAddressFromAbcdWsz(CVY_DEF_ALL_VIP))
  314. {
  315. if (condensed)
  316. Message_print(IDS_CTR_RLS_NO_ALL_VIP_RULES_C);
  317. else
  318. Message_print(IDS_CTR_RLS_NO_ALL_VIP_RULES);
  319. }
  320. else
  321. {
  322. WCHAR szIpAddress[WLBS_MAX_CL_IP_ADDR+1];
  323. AbcdWszFromIpAddress(param1, szIpAddress, ASIZECCH(szIpAddress));
  324. if (condensed)
  325. Message_print(IDS_CTR_RLS_NO_SPECIFIC_VIP_RULES_C, szIpAddress);
  326. else
  327. Message_print(IDS_CTR_RLS_NO_SPECIFIC_VIP_RULES, szIpAddress);
  328. }
  329. }
  330. else
  331. {
  332. if (param1 == IOCTL_ALL_VIPS) {
  333. if (condensed)
  334. Message_print(IDS_CTR_RLS_NONE_C, param2);
  335. else
  336. Message_print(IDS_CTR_RLS_NONE, param2);
  337. }
  338. else if (param1 == IpAddressFromAbcdWsz(CVY_DEF_ALL_VIP))
  339. {
  340. if (condensed)
  341. Message_print(IDS_CTR_RLS_NO_ALL_VIP_RULE_FOR_PORT_C, param2);
  342. else
  343. Message_print(IDS_CTR_RLS_NO_ALL_VIP_RULE_FOR_PORT, param2);
  344. }
  345. else
  346. {
  347. WCHAR szIpAddress[WLBS_MAX_CL_IP_ADDR+1];
  348. AbcdWszFromIpAddress(param1, szIpAddress, ASIZECCH(szIpAddress));
  349. if (condensed)
  350. Message_print(IDS_CTR_RLS_NO_SPECIFIC_VIP_RULE_FOR_PORT_C, szIpAddress, param2);
  351. else
  352. Message_print(IDS_CTR_RLS_NO_SPECIFIC_VIP_RULE_FOR_PORT, szIpAddress, param2);
  353. }
  354. }
  355. return CVY_ERROR_USER;
  356. } else {
  357. switch (command)
  358. {
  359. case enable:
  360. if (condensed)
  361. if (ret_code == WLBS_ALREADY)
  362. Message_print(IDS_CTR_RLS_EN_C_A);
  363. else
  364. Message_print(IDS_CTR_RLS_EN_C);
  365. else
  366. if (ret_code == WLBS_ALREADY)
  367. Message_print(IDS_CTR_RLS_EN_A);
  368. else
  369. Message_print(IDS_CTR_RLS_EN);
  370. break;
  371. case disable:
  372. if (condensed)
  373. if (ret_code == WLBS_ALREADY)
  374. Message_print(IDS_CTR_RLS_DS_C_A);
  375. else
  376. Message_print(IDS_CTR_RLS_DS_C);
  377. else
  378. if (ret_code == WLBS_ALREADY)
  379. Message_print(IDS_CTR_RLS_DS_A);
  380. else
  381. Message_print(IDS_CTR_RLS_DS);
  382. break;
  383. case drain :
  384. if (condensed)
  385. if (ret_code == WLBS_ALREADY)
  386. Message_print(IDS_CTR_RLS_DR_C_A);
  387. else
  388. Message_print(IDS_CTR_RLS_DR_C);
  389. else
  390. if (ret_code == WLBS_ALREADY)
  391. Message_print(IDS_CTR_RLS_DR_A);
  392. else
  393. Message_print(IDS_CTR_RLS_DR);
  394. break;
  395. }
  396. }
  397. break;
  398. case query:
  399. switch (query_state) {
  400. case WLBS_SUSPENDED:
  401. if (condensed)
  402. Message_print(IDS_CTR_CVG_SP_C);
  403. else
  404. Message_print(IDS_CTR_CVG_SP, host_id);
  405. return CVY_OK;
  406. case WLBS_STOPPED:
  407. if (condensed)
  408. Message_print(IDS_CTR_CVG_UN_C);
  409. else
  410. Message_print(IDS_CTR_CVG_UN, host_id);
  411. return CVY_OK;
  412. case WLBS_DISCONNECTED:
  413. if (condensed)
  414. Message_print(IDS_CTR_MEDIA_DISC_C);
  415. else
  416. Message_print(IDS_CTR_MEDIA_DISC, host_id);
  417. return CVY_OK;
  418. case WLBS_DRAINING:
  419. if (condensed)
  420. Message_print(IDS_CTR_CVG_DR_C);
  421. else
  422. Message_print(IDS_CTR_CVG_DR, host_id);
  423. break;
  424. case WLBS_CONVERGING:
  425. if (condensed)
  426. Message_print(IDS_CTR_CVG_PR_C);
  427. else
  428. Message_print(IDS_CTR_CVG_PR, host_id);
  429. break;
  430. case WLBS_CONVERGED:
  431. if (condensed)
  432. Message_print(IDS_CTR_CVG_SL_C);
  433. else
  434. Message_print(IDS_CTR_CVG_SL, host_id);
  435. break;
  436. case WLBS_DEFAULT:
  437. if (condensed)
  438. Message_print(IDS_CTR_CVG_MS_C);
  439. else
  440. Message_print(IDS_CTR_CVG_MS, host_id);
  441. break;
  442. default:
  443. if (condensed)
  444. Message_print(IDS_CTR_CVG_ER_C);
  445. else
  446. Message_print(IDS_CTR_CVG_ER, query_state);
  447. return CVY_ERROR_SYSTEM;
  448. }
  449. if (!condensed) {
  450. first = TRUE;
  451. for (i = 0; i < 32; i ++) {
  452. if (host_map & (1 << i)) {
  453. if (!first)
  454. WConsole (L", ");
  455. else
  456. first = FALSE;
  457. WConsole(L"%d", i + 1);
  458. }
  459. }
  460. WConsole (L"\n");
  461. }
  462. break;
  463. default:
  464. Message_print(IDS_CTR_IO_ER, command);
  465. break;
  466. }
  467. return CVY_OK;
  468. }
  469. //+----------------------------------------------------------------------------
  470. //
  471. // Function: pfnQueryCallback
  472. //
  473. // Description: Callback function to print out received results from remote
  474. // queries as they arrive. Called by Process only.
  475. //
  476. // Arguments: PWLBS_RESPONSE pResponse - response structure from query. The
  477. // only fields guaranteed to be filled out are
  478. // pResponse.status
  479. // pResponse.options.query.flags
  480. // pResponse.options.query.hostname
  481. // pResponse.id
  482. // pResponse.address
  483. //
  484. // Returns: VOID
  485. //
  486. // History: chrisdar 07.31.01 Created
  487. //
  488. //+----------------------------------------------------------------------------
  489. VOID pfnQueryCallback(PWLBS_RESPONSE pResponse)
  490. {
  491. if (NULL == pResponse) { return; }
  492. //
  493. // Print the preamble to the hosts state, e.g., "Host 'hostID' ('ip address') reported: "
  494. //
  495. if (pResponse->address == 0) {
  496. if (pResponse->options.query.flags & NLB_OPTIONS_QUERY_HOSTNAME) {
  497. Message_print(IDS_CTR_HOST_NAME_ONLY, pResponse->id, pResponse->options.query.hostname);
  498. } else {
  499. Message_print(IDS_CTR_HOST_NEITHER, pResponse->id);
  500. }
  501. } else {
  502. DWORD len = CVY_STR_SIZE;
  503. WlbsAddressToString(pResponse->address, wbuf, &len);
  504. if (pResponse->options.query.flags & NLB_OPTIONS_QUERY_HOSTNAME) {
  505. Message_print(IDS_CTR_HOST_BOTH, pResponse->id, pResponse->options.query.hostname, wbuf);
  506. } else {
  507. Message_print(IDS_CTR_HOST_DIP_ONLY, pResponse->id, wbuf);
  508. }
  509. }
  510. if (pResponse->status == WLBS_BAD_PASSW) {
  511. Message_print(IDS_CTR_BAD_PASSW_C);
  512. WConsole(L"\n");
  513. return;
  514. }
  515. //
  516. // Print the state, e.g., "converged as DEFAULT".
  517. // Note: Most of the parameters are hardcoded here because of the constraints
  518. // under which it is valid to call the function callback.
  519. //
  520. // Arg 3 is the response for the API call, which we do not have since the
  521. // function call is not yet complete. Feed it the individual host status,
  522. // since the overall status is just the worst status from the hosts that
  523. // respond anyway.
  524. //
  525. Report(query, TRUE, pResponse->status, 0, 0, pResponse->status, pResponse->id, 0);
  526. }
  527. INT Display (DWORD cluster) {
  528. HANDLE hdl;
  529. HINSTANCE lib;
  530. DWORD flag;
  531. DWORD actual, needed, records, index = 0, got = 0;
  532. DWORD j, i, code;
  533. PWCHAR strp;
  534. PWCHAR prot;
  535. WCHAR aff;
  536. time_t curr_time;
  537. PWLBS_PORT_RULE rp, rulep;
  538. BYTE * inserts[CVY_MAX_INSERTS];
  539. WLBS_REG_PARAMS params;
  540. DWORD status;
  541. status = WlbsReadReg(cluster, &params);
  542. if (status != WLBS_OK) {
  543. Message_print (IDS_CTR_REMOTE);
  544. return CVY_ERROR_USER;
  545. }
  546. Message_print(IDS_CTR_DSP_CONFIGURATION);
  547. WCHAR TimeStr[64];
  548. SYSTEMTIME SysTime;
  549. GetLocalTime(&SysTime);
  550. FormatTheTime(&SysTime, TimeStr, sizeof(TimeStr)/sizeof(WCHAR));
  551. WConsole(L"%-25.25ls = %ls\n", L"Current time", TimeStr);
  552. WConsole(L"%-25.25ls = %d\n", CVY_NAME_VERSION, params.i_parms_ver);
  553. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_VIRTUAL_NIC, params.i_virtual_nic_name);
  554. WConsole(L"%-25.25ls = %d\n", CVY_NAME_ALIVE_PERIOD, params.alive_period);
  555. WConsole(L"%-25.25ls = %d\n", CVY_NAME_ALIVE_TOLER, params.alive_tolerance);
  556. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NUM_ACTIONS, params.num_actions);
  557. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NUM_PACKETS, params.num_packets);
  558. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NUM_SEND_MSGS, params.num_send_msgs);
  559. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_NETWORK_ADDR, params.cl_mac_addr);
  560. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_DOMAIN_NAME, params.domain_name);
  561. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_CL_IP_ADDR, params.cl_ip_addr);
  562. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_CL_NET_MASK, params.cl_net_mask);
  563. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_DED_IP_ADDR, params.ded_ip_addr);
  564. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_DED_NET_MASK, params.ded_net_mask);
  565. WConsole(L"%-25.25ls = %d\n", CVY_NAME_HOST_PRIORITY, params.host_priority);
  566. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_CLUSTER_MODE, (params.cluster_mode == CVY_HOST_STATE_STARTED) ? L"STARTED" :
  567. (params.cluster_mode == CVY_HOST_STATE_STOPPED) ? L"STOPPED" :
  568. (params.cluster_mode == CVY_HOST_STATE_SUSPENDED) ? L"SUSPENDED" : L"UNKNOWN");
  569. WConsole(L"%-25.25ls = ", CVY_NAME_PERSISTED_STATES);
  570. if (!params.persisted_states)
  571. WConsole(L"NONE");
  572. if (params.persisted_states & CVY_PERSIST_STATE_STOPPED) {
  573. WConsole(L"STOPPED");
  574. if ((params.persisted_states &= ~CVY_PERSIST_STATE_STOPPED))
  575. WConsole(L", ");
  576. }
  577. if (params.persisted_states & CVY_PERSIST_STATE_STARTED) {
  578. WConsole(L"STARTED");
  579. if ((params.persisted_states &= ~CVY_PERSIST_STATE_STARTED))
  580. WConsole(L", ");
  581. }
  582. if (params.persisted_states & CVY_PERSIST_STATE_SUSPENDED) {
  583. WConsole(L"SUSPENDED");
  584. if ((params.persisted_states &= ~CVY_PERSIST_STATE_SUSPENDED))
  585. WConsole(L", ");
  586. }
  587. WConsole(L"\n");
  588. WConsole(L"%-25.25ls = %d\n", CVY_NAME_DSCR_PER_ALLOC, params.dscr_per_alloc);
  589. WConsole(L"%-25.25ls = %d\n", CVY_NAME_MAX_DSCR_ALLOCS, params.max_dscr_allocs);
  590. WConsole(L"%-25.25ls = %d\n", CVY_NAME_TCP_TIMEOUT, params.tcp_dscr_timeout);
  591. WConsole(L"%-25.25ls = %d\n", CVY_NAME_IPSEC_TIMEOUT, params.ipsec_dscr_timeout);
  592. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_FILTER_ICMP, params.filter_icmp ? L"ENABLED" : L"DISABLED");
  593. WConsole(L"%-25.25ls = %d\n", CVY_NAME_SCALE_CLIENT, params.i_scale_client);
  594. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NBT_SUPPORT, params.i_nbt_support);
  595. WConsole(L"%-25.25ls = %d\n", CVY_NAME_MCAST_SUPPORT, params.mcast_support);
  596. WConsole(L"%-25.25ls = %d\n", CVY_NAME_MCAST_SPOOF, params.i_mcast_spoof);
  597. WConsole(L"%-25.25ls = %d\n", CVY_NAME_MASK_SRC_MAC, params.mask_src_mac);
  598. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_IGMP_SUPPORT, params.fIGMPSupport ? L"ENABLED" : L"DISABLED");
  599. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_IP_TO_MCASTIP, params.fIpToMCastIp ? L"ENABLED" : L"DISABLED");
  600. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_MCAST_IP_ADDR, params.szMCastIpAddress);
  601. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NETMON_ALIVE, params.i_netmon_alive);
  602. if (params.i_effective_version == CVY_NT40_VERSION_FULL)
  603. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_EFFECTIVE_VERSION, CVY_NT40_VERSION);
  604. else
  605. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_EFFECTIVE_VERSION, CVY_VERSION);
  606. WConsole(L"%-25.25ls = %d\n", CVY_NAME_IP_CHG_DELAY, params.i_ip_chg_delay);
  607. WConsole(L"%-25.25ls = %d\n", CVY_NAME_CONVERT_MAC, params.i_convert_mac);
  608. WConsole(L"%-25.25ls = %d\n", CVY_NAME_CLEANUP_DELAY, params.i_cleanup_delay);
  609. WConsole(L"%-25.25ls = %d\n", CVY_NAME_RCT_ENABLED, params.rct_enabled);
  610. WConsole(L"%-25.25ls = %d\n", CVY_NAME_RCT_PORT, params.rct_port);
  611. WConsole(L"%-25.25ls = 0x%X\n", CVY_NAME_RCT_PASSWORD, params.i_rct_password);
  612. WConsole(L"%-25.25ls = 0x%X\n", CVY_NAME_RMT_PASSWORD, params.i_rmt_password);
  613. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_CUR_VERSION, CVY_VERSION);
  614. WConsole(L"%-25.25ls = 0x%X\n", CVY_NAME_INSTALL_DATE, params.install_date);
  615. WConsole(L"%-25.25ls = 0x%X\n", CVY_NAME_VERIFY_DATE, params.i_verify_date);
  616. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NUM_RULES, params.i_num_rules);
  617. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_BDA_TEAMING, params.bda_teaming.active ? L"ENABLED" : L"DISABLED");
  618. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_BDA_TEAM_ID, params.bda_teaming.team_id);
  619. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_BDA_MASTER, params.bda_teaming.master ? L"ENABLED" : L"DISABLED");
  620. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_BDA_REVERSE_HASH, params.bda_teaming.reverse_hash ? L"ENABLED" : L"DISABLED");
  621. WConsole(L"%-25.25ls = %d\n", CVY_NAME_ID_HB_PERIOD, params.identity_period);
  622. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_ID_HB_ENABLED, params.identity_enabled ? L"ENABLED" : L"DISABLED");
  623. WConsole(L"%-25.25ls \n", CVY_NAME_PORT_RULES);
  624. WConsole(L"Virtual IP addr Start\tEnd\tProt\tMode\t\tPri\tLoad\tAffinity\n");
  625. for (i = 0; i < params.i_num_rules; i ++) {
  626. rp = params.i_port_rules + i;
  627. code = CVY_RULE_CODE_GET(rp);
  628. CVY_RULE_CODE_SET(rp);
  629. if (code != CVY_RULE_CODE_GET(rp)) {
  630. Message_print(IDS_CTR_BAD_RULE_CODE, code, CVY_RULE_CODE_GET(rp));
  631. rp->code = code;
  632. continue;
  633. }
  634. if (!rp->valid) {
  635. Message_print(IDS_CTR_INVALID_RULE);
  636. continue;
  637. }
  638. if (rp->start_port > rp->end_port) {
  639. Message_print(IDS_CTR_BAD_PORT_RANGE, rp->start_port, rp->end_port);
  640. continue;
  641. }
  642. for (j = 0; j < i; j ++) {
  643. rulep = params.i_port_rules + j;
  644. if ((IpAddressFromAbcdWsz(rulep->virtual_ip_addr) == IpAddressFromAbcdWsz(rp->virtual_ip_addr))
  645. && ((rulep->start_port < rp->start_port && rulep->end_port >= rp->start_port) ||
  646. (rulep->start_port >= rp->start_port && rulep->start_port <= rp->end_port))) {
  647. Message_print(IDS_CTR_PORT_RANGE_OVERLAP, i, rp->start_port, rp->end_port, j, rulep->start_port, rulep->end_port);
  648. continue;
  649. }
  650. }
  651. if (rp->start_port > CVY_MAX_PORT) {
  652. Message_print(IDS_CTR_BAD_START_PORT, rp->start_port);
  653. continue;
  654. }
  655. if (rp->end_port > CVY_MAX_PORT) {
  656. Message_print(IDS_CTR_BAD_END_PORT, rp->end_port);
  657. continue;
  658. }
  659. if (rp->protocol < CVY_MIN_PROTOCOL || rp->protocol > CVY_MAX_PROTOCOL) {
  660. Message_print(IDS_CTR_BAD_PROTOCOL, rp->protocol);
  661. continue;
  662. }
  663. if (rp->mode < CVY_MIN_MODE || rp->mode > CVY_MAX_MODE) {
  664. Message_print(IDS_CTR_BAD_MODE, rp->mode);
  665. continue;
  666. }
  667. switch (rp->protocol) {
  668. case CVY_TCP:
  669. prot = L"TCP";
  670. break;
  671. case CVY_UDP:
  672. prot = L"UDP";
  673. break;
  674. default:
  675. prot = L"Both";
  676. break;
  677. }
  678. if (!lstrcmpi(rp->virtual_ip_addr, CVY_DEF_ALL_VIP))
  679. WConsole(L"%15ls\t%5d\t%5d\t%ls\t", L"ALL", rp->start_port, rp->end_port, prot);
  680. else
  681. WConsole(L"%15ls\t%5d\t%5d\t%ls\t", rp->virtual_ip_addr, rp->start_port, rp->end_port, prot);
  682. switch (rp->mode) {
  683. case CVY_SINGLE:
  684. WConsole(L"%-10.10ls\t%2d", L"Single", rp->mode_data.single.priority);
  685. break;
  686. case CVY_MULTI:
  687. if (rp->mode_data.multi.affinity == CVY_AFFINITY_NONE)
  688. aff = L'N';
  689. else if (rp->mode_data.multi.affinity == CVY_AFFINITY_SINGLE)
  690. aff = L'S';
  691. else
  692. aff = L'C';
  693. if (rp->mode_data.multi.equal_load)
  694. WConsole(L"%-10.10ls\t\tEqual\t%lc", L"Multiple", aff);
  695. else {
  696. if (rp->mode_data.multi.load > CVY_MAX_LOAD) {
  697. Message_print(IDS_CTR_BAD_LOAD, rp->mode_data.multi.load);
  698. continue;
  699. }
  700. WConsole(L"%-10.10ls\t\t%3d\t%lc", L"Multiple", rp->mode_data.multi.load, aff);
  701. }
  702. break;
  703. default:
  704. WConsole(L"%-10.10ls", L"Disabled");
  705. break;
  706. }
  707. WConsole(L"\n");
  708. }
  709. WConsole(L"\n");
  710. Message_print(IDS_CTR_DSP_EVENTLOG);
  711. hdl = OpenEventLog (NULL, L"System");
  712. if (hdl == NULL) {
  713. Message_print(IDS_CTR_EVNT_LOG_OPEN_FAIL);
  714. Error_print (FALSE);
  715. return CVY_ERROR_SYSTEM;
  716. }
  717. if (!GetNumberOfEventLogRecords(hdl, &records)) {
  718. Message_print(IDS_CTR_EVNT_LOG_NUM_OF_REC_FAIL);
  719. Error_print (FALSE);
  720. CloseEventLog (hdl);
  721. return CVY_ERROR_SYSTEM;
  722. }
  723. if (!GetOldestEventLogRecord (hdl, & index)) {
  724. Message_print(IDS_CTR_EVNT_LOG_LATEST_REC_FAIL);
  725. Error_print (FALSE);
  726. CloseEventLog (hdl);
  727. return CVY_ERROR_SYSTEM;
  728. }
  729. const WCHAR* pwcszFile = L"\\drivers\\%ls.sys";
  730. UINT uiSysDirLen = GetSystemDirectory (g_PathName, ASIZECCH(g_PathName));
  731. ASSERT( (uiSysDirLen <= (ASIZECCH(g_PathName) - 1)) && (uiSysDirLen != 0) );
  732. HRESULT hr = StringCchPrintf(g_PathName + uiSysDirLen, ASIZECCH(g_PathName) - uiSysDirLen, pwcszFile, CVY_NAME);
  733. ASSERT(hr == S_OK);
  734. lib = LoadLibrary(g_PathName);
  735. if (lib == NULL) {
  736. Message_print(IDS_CTR_LOAD_LIB_FAIL);
  737. Error_print (FALSE);
  738. CloseEventLog (hdl);
  739. return CVY_ERROR_SYSTEM;
  740. }
  741. index += records - 1;
  742. flag = EVENTLOG_SEEK_READ | EVENTLOG_BACKWARDS_READ;
  743. while (got < CVY_MAX_EVENTS && ReadEventLog(hdl, flag, index, g_buffer, sizeof(g_buffer), &actual, &needed)) {
  744. LPBYTE pbCurrent = g_buffer;
  745. while (got < CVY_MAX_EVENTS && actual > 0) {
  746. UNALIGNED EVENTLOGRECORD * recp = (EVENTLOGRECORD *) pbCurrent;
  747. if (wcscmp ((PWSTR)(((PBYTE) recp) + sizeof(EVENTLOGRECORD)), CVY_NAME) == 0) {
  748. time_t TimeGenerated = recp->TimeGenerated;
  749. ConvertTimeToSystemTime(TimeGenerated, TimeStr, sizeof(TimeStr)/sizeof(WCHAR));
  750. strp = (PWCHAR)((LPBYTE)recp + recp->StringOffset);
  751. for (i = 0; i < CVY_MAX_INSERTS; i ++) {
  752. if (i < recp->NumStrings) {
  753. inserts[i] = (BYTE*)strp;
  754. strp += wcslen (strp) + 1;
  755. } else
  756. inserts[i] = 0;
  757. }
  758. DWORD dwStatus = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ARGUMENT_ARRAY, lib,
  759. recp->EventID, 0, (PWCHAR)message, CVY_BUF_SIZE, (va_list *)inserts);
  760. //
  761. // We have multiple message files that store the text for WLBS events, but we are only checking one of them.
  762. // This code is essentially legacy, so instead of fixing it to search all of the message files, we ignore
  763. // "not found" errors.
  764. //
  765. if (dwStatus > 0 || GetLastError() != ERROR_MR_MID_NOT_FOUND)
  766. {
  767. WConsole(L"#%02d ID: 0x%08X Type: %d Category: %d ", index--, recp->EventID, recp->EventType, recp->EventCategory);
  768. WConsole(L"Time: %ls\n", TimeStr);
  769. if (dwStatus == 0) {
  770. WConsole(L"Could not load message string due to:\n");
  771. Error_print(FALSE);
  772. } else
  773. WConsole(L"%ls", message);
  774. for (i = 0; i < recp->DataLength / sizeof(DWORD); i ++) {
  775. if (i != 0 && i % 8 == 0)
  776. WConsole(L"\n");
  777. WConsole(L"%08X ", *(UNALIGNED DWORD*)((PBYTE)recp + recp->DataOffset + i * sizeof(DWORD)));
  778. }
  779. WConsole(L"\n\n");
  780. got++;
  781. }
  782. }
  783. actual -= recp->Length;
  784. pbCurrent += recp->Length;
  785. index--;
  786. }
  787. flag = EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ;
  788. }
  789. FreeLibrary(lib);
  790. CloseEventLog(hdl);
  791. Message_print(IDS_CTR_DSP_IPCONFIG);
  792. fflush(stdout);
  793. const WCHAR* pwcszCmd = L"\\ipconfig.exe";
  794. const WCHAR* pwcszOption = L"/all";
  795. uiSysDirLen = GetSystemDirectory(g_PathName, ASIZECCH(g_PathName));
  796. ASSERT( (uiSysDirLen <= (ASIZECCH(g_PathName) - 1)) && (uiSysDirLen != 0) );
  797. hr = StringCchCat(g_PathName, ASIZECCH(g_PathName), pwcszCmd);
  798. ASSERT(hr == S_OK);
  799. if (_wspawnl(_P_WAIT, g_PathName, g_PathName, pwcszOption, NULL) == -1)
  800. {
  801. const DWORD dwErrno = errno;
  802. if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwErrno, 0, wbuf, CVY_STR_SIZE, NULL) == 0)
  803. {
  804. //
  805. // If we can't resolve the message, then we just print the error code
  806. //
  807. (VOID) StringCchPrintf(wbuf, CVY_STR_SIZE, L"11%d", dwErrno);
  808. }
  809. Message_print(IDS_CTR_CMD_EXEC_FAILED, wbuf);
  810. wbuf[0] = L'\0';
  811. }
  812. Message_print(IDS_CTR_DSP_STATE);
  813. return CVY_OK;
  814. }
  815. /* This function parses the remaining arguments to determine whether the command
  816. * is for all clusters, or a remote cluster or for a single local cluster. */
  817. BOOLEAN Parse (INT argc, PWCHAR argv [], PINT arg_index, PDWORD ptarget_cl, PDWORD ptarget_host) {
  818. PWCHAR phost;
  819. #ifdef BACKWARD_COMPATIBILITY
  820. *ptarget_cl = CVY_ALL_CLUSTERS;
  821. *ptarget_host = CVY_LOCAL_HOST;
  822. if (*arg_index >= argc)
  823. return TRUE;
  824. #endif
  825. /* At this point, argv[arg_index] == cluster_ip and/or argv[arg_index+1] == /local or /passw or /port */
  826. //
  827. // Special check for /PASSW without a cluster ID, because this is
  828. // a common error
  829. //
  830. if ( _wcsicmp (argv [*arg_index], L"/passw") == 0
  831. || _wcsicmp (argv [*arg_index], L"-passw") == 0)
  832. {
  833. Message_print (IDS_CTR_PSSW_WITHOUT_CLUSTER);
  834. return FALSE;
  835. }
  836. phost = wcschr(argv[* arg_index], L':');
  837. /* if there is no host part - operation applies to all hosts */
  838. if (phost == NULL) {
  839. *ptarget_host = CVY_ALL_HOSTS;
  840. } else {
  841. /* split target name so targ points to cluster name and host to host name */
  842. *phost = 0;
  843. phost ++;
  844. if (wcslen(phost) <= 2 && phost[0] >= L'0' && phost[0] <= L'9' && ((phost[1] >= L'0' && phost[1] <= L'9') || phost[1] == 0))
  845. *ptarget_host = _wtoi(phost);
  846. else {
  847. *ptarget_host = WlbsResolve(phost);
  848. if (*ptarget_host == 0) {
  849. Message_print(IDS_CTR_BAD_HOST_NAME_IP);
  850. return FALSE;
  851. }
  852. }
  853. }
  854. // Retrieve the Cluster IP Address or "ALL"
  855. if (_wcsicmp (argv[*arg_index], L"all") == 0)
  856. {
  857. // If there is a host part, then, cluster ip can not be "ALL"
  858. if (*ptarget_host != CVY_ALL_HOSTS)
  859. {
  860. Message_print(IDS_CTR_BAD_CLUSTER_NAME_IP);
  861. return FALSE;
  862. }
  863. *ptarget_cl = CVY_ALL_CLUSTERS;
  864. }
  865. else
  866. {
  867. *ptarget_cl = WlbsResolve(argv[*arg_index]);
  868. if (*ptarget_cl == 0) {
  869. Message_print(IDS_CTR_BAD_CLUSTER_NAME_IP);
  870. return FALSE;
  871. }
  872. }
  873. (*arg_index)++;
  874. // If there is no host part, then, there better be the LOCAL or GLOBAL flag
  875. if (*ptarget_host == CVY_ALL_HOSTS)
  876. {
  877. if (*arg_index == argc)
  878. {
  879. #ifdef BACKWARD_COMPATIBILITY
  880. return TRUE;
  881. #else
  882. Message_print(IDS_CTR_CLUSTER_WITHOUT_LOCAL_GLOBAL_FLAG);
  883. return FALSE;
  884. #endif
  885. }
  886. if (_wcsicmp (argv[*arg_index], L"local") == 0)
  887. {
  888. *ptarget_host = CVY_LOCAL_HOST;
  889. (*arg_index)++;
  890. }
  891. #ifdef BACKWARD_COMPATIBILITY
  892. else if ((argv[*arg_index][0] == L'/') || (argv[*arg_index][0] == L'-'))
  893. {
  894. if (_wcsicmp(argv[*arg_index] + 1, L"local") == 0)
  895. {
  896. *ptarget_host = CVY_LOCAL_HOST;
  897. (*arg_index)++;
  898. }
  899. }
  900. #endif
  901. else if (_wcsicmp (argv[*arg_index], L"global") == 0)
  902. {
  903. // Already set to CVY_ALL_HOSTS
  904. (*arg_index)++;
  905. }
  906. else
  907. {
  908. Message_print(IDS_CTR_CLUSTER_WITHOUT_LOCAL_GLOBAL_FLAG);
  909. return FALSE;
  910. }
  911. }
  912. if (*arg_index == argc)
  913. return TRUE;
  914. if ((argv[*arg_index][0] == L'/') || (argv[*arg_index][0] == L'-')) {
  915. #ifdef BACKWARD_COMPATIBILITY
  916. if (_wcsicmp(argv[*arg_index] + 1, L"local") == 0) {
  917. (*arg_index)++;
  918. *ptarget_host = CVY_LOCAL_HOST;
  919. return TRUE;
  920. } else
  921. #endif
  922. if ((_wcsicmp(argv[*arg_index] + 1, L"port") == 0) || (_wcsicmp(argv[*arg_index] + 1, L"passw") == 0) || (_wcsicmp(argv[*arg_index] + 1, L"commit") == 0))
  923. return TRUE;
  924. else
  925. return FALSE;
  926. } else
  927. return FALSE;
  928. }
  929. VOID Report_convergence_info (ULONG host, ULONG status, PNLB_OPTIONS pOptions) {
  930. /* If the host is stopped, suspended, or disconnected, then no convergence information was returned.
  931. This should be caught by the next check as well, but just in case, check here too. */
  932. if ((status == WLBS_STOPPED) || (status == WLBS_SUSPENDED) || (status == WLBS_DISCONNECTED)) return;
  933. /* If no convergence information was provided, we can bail out here. */
  934. if (!(pOptions->query.flags & NLB_OPTIONS_QUERY_CONVERGENCE)) return;
  935. /* If the time since the last convergence is non-zero, then convergence
  936. has completed. Calculate the time of the last convergence completion
  937. as the current time minus the time since the last convergence. */
  938. if (pOptions->query.LastConvergence == NLB_QUERY_TIME_INVALID) {
  939. /* Convergence is on-going. */
  940. Message_print(IDS_CTR_CONVERGENCE_INCOMPLETE, host, pOptions->query.NumConvergences);
  941. } else {
  942. WCHAR szLast[64]; /* The string returned by _wctime is ALWAYS 26 characters. */
  943. time_t tLast;
  944. /* Get the current time. */
  945. time(&tLast);
  946. /* Decrement time by the elapsed time to get the wall clock time of the
  947. last convergence completion. Note this is not an exact science as the
  948. load module tracks time on a much looser basis than the system does
  949. in general, so the two may be "out of whack" by up to a second, which
  950. can result in two consecutive queries coming up with times for the
  951. last convergence that differ by a second. */
  952. tLast -= pOptions->query.LastConvergence;
  953. ConvertTimeToSystemTime(tLast, szLast, sizeof(szLast)/sizeof(WCHAR));
  954. /* Print the time of the last completed convergence. */
  955. Message_print(IDS_CTR_CONVERGENCE_COMPLETE, host, pOptions->query.NumConvergences, szLast);
  956. }
  957. return;
  958. }
  959. VOID Process (WLBS_COMMANDS command, DWORD target_cl, DWORD target_host, ULONG param1,
  960. ULONG param2, ULONG param3, ULONG dest_port, DWORD dest_addr, PWCHAR dest_password) {
  961. DWORD len = WLBS_MAX_CL_IP_ADDR + 1;
  962. DWORD host_map;
  963. DWORD status;
  964. DWORD i;
  965. WLBS_REG_PARAMS reg_data;
  966. PFN_QUERY_CALLBACK pfnQueryCB = &pfnQueryCallback; // Address of callback function.
  967. DWORD num_hosts = WLBS_MAX_HOSTS;
  968. PWLBS_RESPONSE pResponse = new WLBS_RESPONSE[num_hosts];
  969. if (pResponse == NULL)
  970. {
  971. Message_print(IDS_CTR_FAILED_MALLOC);
  972. return;
  973. }
  974. WlbsPasswordSet(target_cl, dest_password);
  975. WlbsPortSet(target_cl, (USHORT)dest_port);
  976. switch (command) {
  977. case query:
  978. status = WlbsQuery(target_cl, target_host, pResponse, &num_hosts, &host_map, pfnQueryCB);
  979. break;
  980. case __start:
  981. status = WlbsStart(target_cl, target_host, pResponse, &num_hosts);
  982. break;
  983. case stop:
  984. status = WlbsStop(target_cl, target_host, pResponse, &num_hosts);
  985. break;
  986. case suspend:
  987. status = WlbsSuspend(target_cl, target_host, pResponse, &num_hosts);
  988. break;
  989. case resume:
  990. status = WlbsResume(target_cl, target_host, pResponse, &num_hosts);
  991. break;
  992. case drainstop:
  993. status = WlbsDrainStop(target_cl, target_host, pResponse, &num_hosts);
  994. break;
  995. case enable:
  996. status = WlbsEnable(target_cl, target_host, pResponse, &num_hosts, param1, param2);
  997. break;
  998. case disable:
  999. status = WlbsDisable(target_cl, target_host, pResponse, &num_hosts, param1, param2);
  1000. break;
  1001. case drain:
  1002. status = WlbsDrain(target_cl, target_host, pResponse, &num_hosts, param1, param2);
  1003. break;
  1004. case reload:
  1005. status = WlbsNotifyConfigChange(target_cl);
  1006. if (status == WLBS_LOCAL_ONLY) {
  1007. Message_print(IDS_CTR_REMOTE);
  1008. goto end;
  1009. }
  1010. if (status == WLBS_REG_ERROR || status == WLBS_BAD_PARAMS) {
  1011. Message_print(IDS_CTR_BAD_PARAMS);
  1012. goto end;
  1013. }
  1014. if (status == WLBS_OK) {
  1015. Message_print(IDS_CTR_RELOADED);
  1016. goto end;
  1017. }
  1018. break;
  1019. case display:
  1020. Display(target_cl);
  1021. Process(query, target_cl, target_host, param1, param2, param3, dest_port, dest_addr, dest_password);
  1022. goto end;
  1023. case registry:
  1024. if ((status = WlbsReadReg(target_cl, &reg_data)) != WLBS_OK) {
  1025. Message_print(IDS_CTR_REG_READ);
  1026. goto end;
  1027. }
  1028. switch (param1) {
  1029. case mcastipaddress:
  1030. reg_data.fIpToMCastIp = FALSE;
  1031. WlbsAddressToString(param2, reg_data.szMCastIpAddress, &len);
  1032. break;
  1033. case iptomcastip:
  1034. reg_data.fIpToMCastIp = param2;
  1035. break;
  1036. case iptomacenable:
  1037. reg_data.i_convert_mac = param2;
  1038. break;
  1039. case masksrcmac:
  1040. reg_data.mask_src_mac = param2;
  1041. break;
  1042. case netmonalivemsgs:
  1043. reg_data.i_netmon_alive = param2;
  1044. break;
  1045. }
  1046. if ((status = WlbsWriteReg(target_cl, &reg_data)) != WLBS_OK) {
  1047. Message_print(IDS_CTR_REG_WRITE);
  1048. goto end;
  1049. }
  1050. /* Reload the driver, if /COMMIT was specified. */
  1051. if (param3)
  1052. Process(reload, target_cl, target_host, param1, param2, param3, dest_port, dest_addr, dest_password);
  1053. switch (param1) {
  1054. case mcastipaddress:
  1055. {
  1056. TCHAR igmpaddr[WLBS_MAX_CL_IP_ADDR + 1];
  1057. DWORD dwIgmpAddrLen = WLBS_MAX_CL_IP_ADDR + 1;
  1058. WlbsAddressToString (param2, igmpaddr, &dwIgmpAddrLen);
  1059. Message_print(IDS_CTR_REG_MCASTIPADDRESS, igmpaddr);
  1060. break;
  1061. }
  1062. case iptomcastip:
  1063. Message_print((param2) ? IDS_CTR_REG_IPTOMCASTIP_ON : IDS_CTR_REG_IPTOMCASTIP_OFF);
  1064. break;
  1065. case masksrcmac:
  1066. Message_print((param2) ? IDS_CTR_REG_MASKSRCMAC_ON : IDS_CTR_REG_MASKSRCMAC_OFF);
  1067. break;
  1068. case iptomacenable:
  1069. Message_print((param2) ? IDS_CTR_REG_IPTOMACENABLE_ON : IDS_CTR_REG_IPTOMACENABLE_OFF);
  1070. break;
  1071. case netmonalivemsgs:
  1072. Message_print((param2) ? IDS_CTR_REG_NETMONALIVEMSGS_ON : IDS_CTR_REG_NETMONALIVEMSGS_OFF);
  1073. break;
  1074. }
  1075. goto end;
  1076. default:
  1077. goto end;
  1078. }
  1079. if (status == WLBS_INIT_ERROR) {
  1080. Message_print(IDS_CTR_INIT);
  1081. goto end;
  1082. }
  1083. if (status == WLBS_IO_ERROR) {
  1084. if (command == drain || command == disable || command == enable)
  1085. {
  1086. Message_print(IDS_CTR_PORTRULE_NOT_FOUND_OR_IOCTL_FAILED);
  1087. }
  1088. else
  1089. {
  1090. Message_print(IDS_CTR_IO_ERROR);
  1091. }
  1092. goto end;
  1093. }
  1094. if (status == WLBS_LOCAL_ONLY) {
  1095. Message_print(IDS_CTR_WSOCK);
  1096. goto end;
  1097. }
  1098. if (status == WLBS_REMOTE_ONLY) {
  1099. Message_print(IDS_CTR_NO_CVY, CVY_NAME);
  1100. goto end;
  1101. }
  1102. if (status >= WSABASEERR) {
  1103. Message_print(IDS_CTR_WSOCK);
  1104. Error_print(TRUE);
  1105. goto end;
  1106. }
  1107. if (status == WLBS_TIMEOUT) {
  1108. Message_print(IDS_CTR_NO_RSP3);
  1109. if (command != query)
  1110. Message_print(IDS_CTR_NO_RSP4, CVY_NAME);
  1111. goto end;
  1112. }
  1113. if (status == WLBS_NOT_FOUND) {
  1114. Message_print(IDS_CTR_NOT_FOUND);
  1115. goto end;
  1116. }
  1117. if (target_host == CVY_LOCAL_HOST) {
  1118. if (command == query)
  1119. {
  1120. //
  1121. // A query requires that at least one host responded for use to print out information
  1122. //
  1123. if (num_hosts == 0)
  1124. {
  1125. goto end;
  1126. }
  1127. Report_convergence_info(pResponse[0].id, pResponse[0].status, &pResponse[0].options);
  1128. Report(command, FALSE, status, param1, param2, pResponse[0].status, pResponse[0].id, host_map);
  1129. }
  1130. else
  1131. {
  1132. //
  1133. // All commands other than query ignore the "status" and "id" information
  1134. //
  1135. ULONG ulStatus = 0;
  1136. ULONG ulId = 0;
  1137. Report(command, FALSE, status, param1, param2, ulStatus, ulId, host_map);
  1138. }
  1139. goto end;
  1140. }
  1141. /* The callback function, if provided, prints report information. Return
  1142. here if we have a callback for a query operation */
  1143. if (command == query && NULL != pfnQueryCB) {
  1144. goto end;
  1145. }
  1146. /* Call Report for each host's response */
  1147. for (i = 0; i < num_hosts; i++) {
  1148. if (pResponse[i].address == 0) {
  1149. if (pResponse[i].options.query.flags & NLB_OPTIONS_QUERY_HOSTNAME) {
  1150. Message_print(IDS_CTR_HOST_NAME_ONLY, pResponse[i].id, pResponse[i].options.query.hostname);
  1151. } else {
  1152. Message_print(IDS_CTR_HOST_NEITHER, pResponse[i].id);
  1153. }
  1154. } else {
  1155. DWORD dwAddrLen = CVY_STR_SIZE;
  1156. WlbsAddressToString(pResponse[i].address, wbuf, &dwAddrLen);
  1157. if (pResponse[i].options.query.flags & NLB_OPTIONS_QUERY_HOSTNAME) {
  1158. Message_print(IDS_CTR_HOST_BOTH, pResponse[i].id, pResponse[i].options.query.hostname, wbuf);
  1159. } else {
  1160. Message_print(IDS_CTR_HOST_DIP_ONLY, pResponse[i].id, wbuf);
  1161. }
  1162. }
  1163. if (pResponse[i].status == WLBS_BAD_PASSW) {
  1164. if (target_host != CVY_ALL_HOSTS) {
  1165. WConsole(L"\n");
  1166. Message_print(IDS_CTR_BAD_PASSW);
  1167. } else {
  1168. Message_print(IDS_CTR_BAD_PASSW_C);
  1169. WConsole(L"\n");
  1170. }
  1171. continue;
  1172. }
  1173. Report(command, TRUE, pResponse[i].status, param1, param2, pResponse[i].status, pResponse[i].id, host_map);
  1174. }
  1175. end:
  1176. delete [] pResponse;
  1177. return;
  1178. }
  1179. VOID Report_port_state (WLBS_RESPONSE response) {
  1180. WCHAR PacketsAccepted[CVY_STR_SIZE];
  1181. WCHAR PacketsDropped[CVY_STR_SIZE];
  1182. WCHAR BytesAccepted[CVY_STR_SIZE];
  1183. WCHAR BytesDropped[CVY_STR_SIZE];
  1184. if (response.status != WLBS_OK) {
  1185. Message_print(IDS_CTR_QUERY_PORT_FAILED);
  1186. return;
  1187. }
  1188. switch (response.options.state.port.Status) {
  1189. case NLB_PORT_RULE_NOT_FOUND:
  1190. Message_print(IDS_CTR_QUERY_PORT_NOT_FOUND);
  1191. break;
  1192. case NLB_PORT_RULE_ENABLED:
  1193. (VOID) StringCchPrintf(PacketsAccepted, ASIZECCH(PacketsAccepted), L"%I64u", response.options.state.port.Statistics.Packets.Accepted);
  1194. (VOID) StringCchPrintf(PacketsDropped, ASIZECCH(PacketsDropped), L"%I64u", response.options.state.port.Statistics.Packets.Dropped);
  1195. Message_print(IDS_CTR_QUERY_PORT_ENABLED);
  1196. Message_print(IDS_CTR_QUERY_PORT_STATISTICS, PacketsAccepted, PacketsDropped);
  1197. break;
  1198. case NLB_PORT_RULE_DISABLED:
  1199. Message_print(IDS_CTR_QUERY_PORT_DISABLED);
  1200. break;
  1201. case NLB_PORT_RULE_DRAINING:
  1202. Message_print(IDS_CTR_QUERY_PORT_DRAINING);
  1203. break;
  1204. default:
  1205. Message_print(IDS_CTR_QUERY_PORT_UNKNOWN);
  1206. break;
  1207. }
  1208. return;
  1209. }
  1210. VOID Report_bda_state (WLBS_RESPONSE response) {
  1211. WCHAR ipaddr[CVY_STR_SIZE];
  1212. DWORD len;
  1213. DWORD index;
  1214. if (response.status == WLBS_NOT_FOUND) {
  1215. Message_print(IDS_CTR_QUERY_BDA_NOT_FOUND);
  1216. return;
  1217. }
  1218. if (response.status != WLBS_OK) {
  1219. Message_print(IDS_CTR_QUERY_BDA_FAILED);
  1220. return;
  1221. }
  1222. len = CVY_STR_SIZE;
  1223. WlbsAddressToString(response.options.state.bda.Team.Master, ipaddr, &len);
  1224. if (response.options.state.bda.Team.Active)
  1225. WConsole(L"%-22.22ls = %ls\n", L"Active", L"Yes");
  1226. else if ((response.options.state.bda.Team.MembershipMap != response.options.state.bda.Team.ConsistencyMap) && !response.options.state.bda.Team.Master)
  1227. WConsole(L"%-22.22ls = %ls\n", L"Active", L"No (Inconsistent configuration detected / No master specified)");
  1228. else if (response.options.state.bda.Team.MembershipMap != response.options.state.bda.Team.ConsistencyMap)
  1229. WConsole(L"%-22.22ls = %ls\n", L"Active", L"No (Inconsistent configuration detected)");
  1230. else if (!response.options.state.bda.Team.Master)
  1231. WConsole(L"%-22.22ls = %ls\n", L"Active", L"No (No master specified)");
  1232. else
  1233. WConsole(L"%-22.22ls = %ls\n", L"Active", L"No (Unknown reason)");
  1234. WConsole(L"%-22.22ls = %08x\n", L"Membership fingerprint", response.options.state.bda.Team.MembershipFingerprint);
  1235. WConsole(L"%-22.22ls = %08x\n", L"Membership map", response.options.state.bda.Team.MembershipMap);
  1236. WConsole(L"%-22.22ls = %08x\n", L"Consistency map", response.options.state.bda.Team.ConsistencyMap);
  1237. WConsole(L"%-22.22ls = %ls\n", L"Master", ipaddr);
  1238. WConsole(L"\n%ls (%d)\n", L"Members", response.options.state.bda.Team.MembershipCount);
  1239. for (index = 0; index < response.options.state.bda.Team.MembershipCount; index++) {
  1240. len = CVY_STR_SIZE;
  1241. WlbsAddressToString(response.options.state.bda.Team.Members[index].ClusterIPAddress, ipaddr, &len);
  1242. WConsole(L"%ls %ls:\n", L"Cluster", ipaddr);
  1243. WConsole(L" %-20.20ls = %d\n", L"Member ID", response.options.state.bda.Team.Members[index].MemberID);
  1244. WConsole(L" %-20.20ls = %ls\n", L"Master", response.options.state.bda.Team.Members[index].Master ? L"Yes" : L"No");
  1245. WConsole(L" %-20.20ls = %ls\n", L"Reverse hash", response.options.state.bda.Team.Members[index].ReverseHash ? L"Yes" : L"No");
  1246. if (index < (response.options.state.bda.Team.MembershipCount - 1)) WConsole(L"\n");
  1247. }
  1248. return;
  1249. }
  1250. VOID Report_filter_state (WLBS_RESPONSE response) {
  1251. if (response.status != WLBS_OK) {
  1252. Message_print(IDS_CTR_QUERY_FILTER_FAILED);
  1253. return;
  1254. }
  1255. switch (response.options.state.filter.Accept) {
  1256. case NLB_REJECT_LOAD_MODULE_INACTIVE:
  1257. Message_print(IDS_CTR_QUERY_FILTER_REJECT_LOAD_INACTIVE);
  1258. break;
  1259. case NLB_REJECT_CLUSTER_STOPPED:
  1260. Message_print(IDS_CTR_QUERY_FILTER_REJECT_CLUSTER_STOPPED);
  1261. break;
  1262. case NLB_REJECT_PORT_RULE_DISABLED:
  1263. Message_print(IDS_CTR_QUERY_FILTER_REJECT_RULE_DISABLED);
  1264. break;
  1265. case NLB_REJECT_CONNECTION_DIRTY:
  1266. Message_print(IDS_CTR_QUERY_FILTER_REJECT_CONNECTION_DIRTY);
  1267. break;
  1268. case NLB_REJECT_OWNED_ELSEWHERE:
  1269. Message_print(IDS_CTR_QUERY_FILTER_REJECT_OWNED_ELSEWHERE);
  1270. break;
  1271. case NLB_REJECT_BDA_TEAMING_REFUSED:
  1272. Message_print(IDS_CTR_QUERY_FILTER_REJECT_BDA_REFUSED);
  1273. break;
  1274. case NLB_REJECT_DIP:
  1275. Message_print(IDS_CTR_QUERY_FILTER_REJECT_DIP);
  1276. break;
  1277. case NLB_REJECT_HOOK:
  1278. Message_print(IDS_CTR_QUERY_FILTER_REJECT_HOOK);
  1279. break;
  1280. case NLB_ACCEPT_UNCONDITIONAL_OWNERSHIP:
  1281. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_OWNED);
  1282. break;
  1283. case NLB_ACCEPT_FOUND_MATCHING_DESCRIPTOR:
  1284. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_DESCRIPTOR_FOUND);
  1285. break;
  1286. case NLB_ACCEPT_PASSTHRU_MODE:
  1287. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_PASSTHRU);
  1288. break;
  1289. case NLB_ACCEPT_DIP:
  1290. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_DIP);
  1291. break;
  1292. case NLB_ACCEPT_BROADCAST:
  1293. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_BCAST);
  1294. break;
  1295. case NLB_ACCEPT_REMOTE_CONTROL_REQUEST:
  1296. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_RCTL_REQUEST);
  1297. break;
  1298. case NLB_ACCEPT_REMOTE_CONTROL_RESPONSE:
  1299. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_RCTL_RESPONSE);
  1300. break;
  1301. case NLB_ACCEPT_HOOK:
  1302. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_HOOK);
  1303. break;
  1304. case NLB_ACCEPT_UNFILTERED:
  1305. Message_print(IDS_CTR_QUERY_FILTER_ACCEPT_UNFILTERED);
  1306. break;
  1307. case NLB_UNKNOWN_NO_AFFINITY:
  1308. Message_print(IDS_CTR_QUERY_FILTER_UNKNOWN_NO_AFFINITY);
  1309. break;
  1310. default:
  1311. Message_print(IDS_CTR_QUERY_FILTER_UNKNOWN);
  1312. break;
  1313. }
  1314. if (response.options.state.filter.HashInfo.Valid) {
  1315. WCHAR CurrentMap[CVY_STR_SIZE];
  1316. WCHAR AllIdleMap[CVY_STR_SIZE];
  1317. (VOID) StringCchPrintf(CurrentMap, ASIZECCH(CurrentMap), L"0x%015I64x", response.options.state.filter.HashInfo.CurrentMap);
  1318. (VOID) StringCchPrintf(AllIdleMap, ASIZECCH(AllIdleMap), L"0x%015I64x", response.options.state.filter.HashInfo.AllIdleMap);
  1319. Message_print(IDS_CTR_QUERY_FILTER_HASH_INFO, response.options.state.filter.HashInfo.Bin,
  1320. CurrentMap, AllIdleMap, response.options.state.filter.HashInfo.ActiveConnections);
  1321. }
  1322. if (response.options.state.filter.DescriptorInfo.Valid) {
  1323. Message_print(IDS_CTR_QUERY_FILTER_DESCRIPTOR_INFO, (response.options.state.filter.DescriptorInfo.Alloc) ? L"Yes" : L"No",
  1324. (response.options.state.filter.DescriptorInfo.Dirty) ? L"Yes" : L"No", response.options.state.filter.DescriptorInfo.RefCount);
  1325. }
  1326. return;
  1327. }
  1328. //+----------------------------------------------------------------------------
  1329. //
  1330. // Function: RetrieveStringFromRc
  1331. //
  1332. // Description: Retrieve a string from the log_msgs resource file based on
  1333. // the message id passed in by the user. The string is stored in
  1334. // the global buffer 'message'.
  1335. //
  1336. // Arguments: DWORD id - message ID of the string resource
  1337. //
  1338. // Returns: WCHAR* - pointer to the global buffer containing the resource
  1339. // string. If the lookup fails, the pointer will point to
  1340. // an empty string. The return pointer is always valid.
  1341. //
  1342. // History: ChrisDar, Created 2002 June 11
  1343. //
  1344. // Notes: This function uses a global buffer for storing the output string.
  1345. //+----------------------------------------------------------------------------
  1346. WCHAR* RetrieveStringFromRc(DWORD id)
  1347. {
  1348. //
  1349. // Specifying FORMAT_MESSAGE_MAX_WIDTH_MASK here to prevent FormatMessage from introducing line breaks.
  1350. //
  1351. if (FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, id, 0, message, sizeof(message)-sizeof(WCHAR), NULL) == 0) {
  1352. message[0] = UNICODE_NULL;
  1353. }
  1354. return message;
  1355. }
  1356. VOID Report_params_state (WLBS_RESPONSE response) {
  1357. DWORD index;
  1358. if (response.status != WLBS_OK) {
  1359. Message_print(IDS_CTR_QUERY_PARAMS_FAILED);
  1360. return;
  1361. }
  1362. WCHAR TimeStr[64];
  1363. SYSTEMTIME SysTime;
  1364. GetLocalTime(&SysTime);
  1365. FormatTheTime(&SysTime, TimeStr, sizeof(TimeStr)/sizeof(WCHAR));
  1366. WConsole(L"%-25.25ls = %ls\n", RetrieveStringFromRc(IDS_CTR_CURR_TIME), TimeStr);
  1367. WConsole(L"%-25.25ls = %ls\n", RetrieveStringFromRc(IDS_CTR_HOSTNAME), response.options.state.params.HostName);
  1368. WConsole(L"%-25.25ls = %d\n", CVY_NAME_VERSION, response.options.state.params.Version);
  1369. WConsole(L"%-25.25ls = %08x\n", CVY_NAME_CUR_VERSION, CVY_VERSION_FULL);
  1370. WConsole(L"%-25.25ls = %08x\n", CVY_NAME_EFFECTIVE_VERSION, response.options.state.params.EffectiveVersion);
  1371. WConsole(L"%-25.25ls = %08X\n", CVY_NAME_INSTALL_DATE, response.options.state.params.InstallDate);
  1372. WConsole(L"%-25.25ls = %d\n", CVY_NAME_HOST_PRIORITY, response.options.state.params.HostPriority);
  1373. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_CL_IP_ADDR, response.options.state.params.ClusterIPAddress);
  1374. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_CL_NET_MASK, response.options.state.params.ClusterNetmask);
  1375. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_DED_IP_ADDR, response.options.state.params.DedicatedIPAddress);
  1376. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_DED_NET_MASK, response.options.state.params.DedicatedNetmask);
  1377. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_MCAST_IP_ADDR, response.options.state.params.IGMPMulticastIPAddress);
  1378. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_DOMAIN_NAME, response.options.state.params.DomainName);
  1379. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_NETWORK_ADDR, response.options.state.params.ClusterMACAddress);
  1380. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_CONVERT_MAC, response.options.state.params.ClusterIPToMAC ? L"ENABLED" : L"DISABLED");
  1381. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_MCAST_SUPPORT, response.options.state.params.MulticastSupport ? L"ENABLED" : L"DISABLED");
  1382. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_IGMP_SUPPORT, response.options.state.params.IGMPSupport ? L"ENABLED" : L"DISABLED");
  1383. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_MCAST_SPOOF, response.options.state.params.MulticastSpoof ? L"ENABLED" : L"DISABLED");
  1384. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_MASK_SRC_MAC, response.options.state.params.MaskSourceMAC ? L"ENABLED" : L"DISABLED");
  1385. WConsole(L"%-25.25ls = %d\n", CVY_NAME_ALIVE_PERIOD, response.options.state.params.HeartbeatPeriod);
  1386. WConsole(L"%-25.25ls = %d\n", CVY_NAME_ALIVE_TOLER, response.options.state.params.HeartbeatLossTolerance);
  1387. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NUM_ACTIONS, response.options.state.params.NumActionsAlloc);
  1388. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NUM_PACKETS, response.options.state.params.NumPacketsAlloc);
  1389. WConsole(L"%-25.25ls = %d\n", CVY_NAME_NUM_SEND_MSGS, response.options.state.params.NumHeartbeatsAlloc);
  1390. WConsole(L"%-25.25ls = %d\n", CVY_NAME_DSCR_PER_ALLOC, response.options.state.params.DescriptorsPerAlloc);
  1391. WConsole(L"%-25.25ls = %d\n", CVY_NAME_MAX_DSCR_ALLOCS, response.options.state.params.MaximumDescriptorAllocs);
  1392. WConsole(L"%-25.25ls = %d\n", CVY_NAME_TCP_TIMEOUT, response.options.state.params.TCPConnectionTimeout);
  1393. WConsole(L"%-25.25ls = %d\n", CVY_NAME_IPSEC_TIMEOUT, response.options.state.params.IPSecConnectionTimeout);
  1394. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_FILTER_ICMP, response.options.state.params.FilterICMP ? L"ENABLED" : L"DISABLED");
  1395. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_CLUSTER_MODE, (response.options.state.params.ClusterModeOnStart == CVY_HOST_STATE_STARTED) ? L"STARTED" :
  1396. (response.options.state.params.ClusterModeOnStart == CVY_HOST_STATE_STOPPED) ? L"STOPPED" :
  1397. (response.options.state.params.ClusterModeOnStart == CVY_HOST_STATE_SUSPENDED) ? L"SUSPENDED" : L"UNKNOWN");
  1398. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_HOST_STATE, (response.options.state.params.HostState == CVY_HOST_STATE_STOPPED) ? L"STOPPED" :
  1399. (response.options.state.params.HostState == CVY_HOST_STATE_STARTED) ? L"STARTED" :
  1400. (response.options.state.params.HostState == CVY_HOST_STATE_SUSPENDED) ? L"SUSPENDED" : L"UNKNOWN");
  1401. WConsole(L"%-25.25ls = ", CVY_NAME_PERSISTED_STATES);
  1402. if (!response.options.state.params.PersistedStates)
  1403. WConsole(L"NONE");
  1404. if (response.options.state.params.PersistedStates & CVY_PERSIST_STATE_STOPPED) {
  1405. WConsole(L"STOPPED");
  1406. if ((response.options.state.params.PersistedStates &= ~CVY_PERSIST_STATE_STOPPED))
  1407. WConsole(L", ");
  1408. }
  1409. if (response.options.state.params.PersistedStates & CVY_PERSIST_STATE_STARTED) {
  1410. WConsole(L"STARTED");
  1411. if ((response.options.state.params.PersistedStates &= ~CVY_PERSIST_STATE_STARTED))
  1412. WConsole(L", ");
  1413. }
  1414. if (response.options.state.params.PersistedStates & CVY_PERSIST_STATE_SUSPENDED) {
  1415. WConsole(L"SUSPENDED");
  1416. if ((response.options.state.params.PersistedStates &= ~CVY_PERSIST_STATE_SUSPENDED))
  1417. WConsole(L", ");
  1418. }
  1419. WConsole(L"\n");
  1420. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_SCALE_CLIENT, response.options.state.params.ScaleClient ? L"ENABLED" : L"DISABLED");
  1421. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_NBT_SUPPORT, response.options.state.params.NBTSupport ? L"ENABLED" : L"DISABLED");
  1422. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_NETMON_ALIVE, response.options.state.params.NetmonReceiveHeartbeats ? L"ENABLED" : L"DISABLED");
  1423. WConsole(L"%-25.25ls = %d\n", CVY_NAME_IP_CHG_DELAY, response.options.state.params.IPChangeDelay);
  1424. WConsole(L"%-25.25ls = %d\n", CVY_NAME_CLEANUP_DELAY, response.options.state.params.ConnectionCleanUpDelay);
  1425. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_RCT_ENABLED, response.options.state.params.RemoteControlEnabled ? L"ENABLED" : L"DISABLED");
  1426. WConsole(L"%-25.25ls = %d\n", CVY_NAME_RCT_PORT, response.options.state.params.RemoteControlPort);
  1427. WConsole(L"%-25.25ls = %08X\n", CVY_NAME_RCT_PASSWORD, response.options.state.params.RemoteControlPassword);
  1428. WConsole(L"%-25.25ls = %08X\n", CVY_NAME_RMT_PASSWORD, response.options.state.params.RemoteMaintenancePassword);
  1429. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_BDA_TEAMING, response.options.state.params.BDATeaming.Active ? L"YES" : L"NO");
  1430. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_BDA_TEAM_ID, response.options.state.params.BDATeaming.TeamID);
  1431. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_BDA_MASTER, response.options.state.params.BDATeaming.Master ? L"YES" : L"NO");
  1432. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_BDA_REVERSE_HASH, response.options.state.params.BDATeaming.ReverseHash ? L"YES" : L"NO");
  1433. WConsole(L"%-25.25ls = %d\n", CVY_NAME_ID_HB_PERIOD, response.options.state.params.IdentityHeartbeatPeriod);
  1434. WConsole(L"%-25.25ls = %ls\n", CVY_NAME_ID_HB_ENABLED, response.options.state.params.IdentityHeartbeatEnabled ? L"ENABLED" : L"DISABLED");
  1435. WConsole(L"\n%ls (%d):\n", CVY_NAME_PORT_RULES, response.options.state.params.NumPortRules);
  1436. WConsole(L"\n VIP Start End Prot Mode Pri Load Affinity\n");
  1437. WConsole(L"--------------- ----- ----- ---- -------- --- ---- --------\n");
  1438. for (index = 0; index < response.options.state.params.NumPortRules; index++) {
  1439. NLB_OPTIONS_PARAMS_PORT_RULE * rp = response.options.state.params.PortRules + index;
  1440. DWORD len = CVY_STR_SIZE;
  1441. WCHAR vip[CVY_STR_SIZE];
  1442. PWCHAR protocol;
  1443. PWCHAR affinity;
  1444. switch (rp->Protocol) {
  1445. case CVY_TCP:
  1446. protocol = L"TCP";
  1447. break;
  1448. case CVY_UDP:
  1449. protocol = L"UDP";
  1450. break;
  1451. case CVY_TCP_UDP:
  1452. protocol = L"Both";
  1453. break;
  1454. default:
  1455. protocol = L"Unknown";
  1456. break;
  1457. }
  1458. WlbsAddressToString(rp->VirtualIPAddress, vip, &len);
  1459. if (rp->VirtualIPAddress == CVY_ALL_VIP_NUMERIC_VALUE)
  1460. WConsole(L"%-15ls %5d %5d %-4ls ", L"All", rp->StartPort, rp->EndPort, protocol);
  1461. else
  1462. WConsole(L"%-15ls %5d %5d %-4ls ", vip, rp->StartPort, rp->EndPort, protocol);
  1463. switch (rp->Mode) {
  1464. case CVY_SINGLE:
  1465. WConsole(L"%-8ls %3d\n", L"Single", rp->SingleHost.Priority);
  1466. break;
  1467. case CVY_MULTI:
  1468. switch (rp->MultipleHost.Affinity) {
  1469. case CVY_AFFINITY_NONE:
  1470. affinity = L"None";
  1471. break;
  1472. case CVY_AFFINITY_SINGLE:
  1473. affinity = L"Single";
  1474. break;
  1475. case CVY_AFFINITY_CLASSC:
  1476. affinity = L"Class C";
  1477. break;
  1478. default:
  1479. affinity = L"Unknown";
  1480. break;
  1481. }
  1482. if (rp->MultipleHost.Equal)
  1483. WConsole(L"%-8ls %-3ls %4ls %-ls\n", L"Multiple", L"", L"Eql", affinity);
  1484. else
  1485. WConsole(L"%-8ls %-3ls %4d %-ls\n", L"Multiple", L"", rp->MultipleHost.LoadWeight, affinity);
  1486. break;
  1487. case CVY_NEVER:
  1488. WConsole(L"%-8ls\n", L"Disabled");
  1489. break;
  1490. default:
  1491. WConsole(L"%-8ls\n", RetrieveStringFromRc(IDS_CTR_UNK_FILTER_MODE));
  1492. break;
  1493. }
  1494. }
  1495. WConsole(L"\n%ls\n\n", RetrieveStringFromRc(IDS_CTR_STATS));
  1496. WConsole(L"%-35.35ls = %u\n", RetrieveStringFromRc(IDS_CTR_NUM_ACTIVE_CONN), response.options.state.params.Statistics.ActiveConnections);
  1497. WConsole(L"%-35.35ls = %u\n", RetrieveStringFromRc(IDS_CTR_NUM_DSCR_ALLOC), response.options.state.params.Statistics.DescriptorsAllocated);
  1498. }
  1499. VOID Process_state (WLBS_COMMANDS command, DWORD target_cl, DWORD target_host, PNLB_OPTIONS optionsp, ULONG dest_port, PWCHAR dest_password) {
  1500. DWORD status;
  1501. DWORD ioctl;
  1502. DWORD i;
  1503. DWORD dwNumHosts = WLBS_MAX_HOSTS;
  1504. PWLBS_RESPONSE pResponse = new WLBS_RESPONSE[WLBS_MAX_HOSTS];
  1505. if (pResponse == NULL)
  1506. {
  1507. Message_print(IDS_CTR_FAILED_MALLOC);
  1508. return;
  1509. }
  1510. WlbsPasswordSet(target_cl, dest_password);
  1511. WlbsPortSet(target_cl, (USHORT)dest_port);
  1512. switch (command) {
  1513. case params:
  1514. ioctl = IOCTL_CVY_QUERY_PARAMS;
  1515. break;
  1516. case bdateam:
  1517. ioctl = IOCTL_CVY_QUERY_BDA_TEAMING;
  1518. break;
  1519. case queryport:
  1520. ioctl = IOCTL_CVY_QUERY_PORT_STATE;
  1521. break;
  1522. case filter:
  1523. ioctl = IOCTL_CVY_QUERY_FILTER;
  1524. break;
  1525. default:
  1526. Message_print(IDS_CTR_QUERY_UNKNOWN);
  1527. goto end;
  1528. }
  1529. status = WlbsQueryState(target_cl, target_host, ioctl, optionsp, pResponse, &dwNumHosts);
  1530. if (status == WLBS_INIT_ERROR) {
  1531. Message_print(IDS_CTR_INIT);
  1532. goto end;
  1533. }
  1534. if (status == WLBS_LOCAL_ONLY) {
  1535. switch (command) {
  1536. case params:
  1537. case bdateam:
  1538. Message_print(IDS_CTR_REMOTE);
  1539. break;
  1540. case queryport:
  1541. case filter:
  1542. Message_print(IDS_CTR_WSOCK);
  1543. break;
  1544. default:
  1545. Message_print(IDS_CTR_QUERY_UNKNOWN);
  1546. goto end;
  1547. }
  1548. goto end;
  1549. }
  1550. if (status == WLBS_REMOTE_ONLY) {
  1551. Message_print(IDS_CTR_NO_CVY, CVY_NAME);
  1552. goto end;
  1553. }
  1554. if (status >= WSABASEERR) {
  1555. Message_print(IDS_CTR_WSOCK);
  1556. Error_print(TRUE);
  1557. goto end;
  1558. }
  1559. if (status == WLBS_TIMEOUT) {
  1560. Message_print(IDS_CTR_NO_RSP3);
  1561. Message_print(IDS_CTR_NO_RSP4, CVY_NAME);
  1562. goto end;
  1563. }
  1564. switch (command) {
  1565. case params:
  1566. Message_print(IDS_CTR_QUERY_PARAMS_HDR);
  1567. break;
  1568. case bdateam:
  1569. Message_print(IDS_CTR_QUERY_BDA_HDR, optionsp->state.bda.TeamID);
  1570. break;
  1571. case queryport:
  1572. {
  1573. WCHAR port[CVY_STR_SIZE];
  1574. WCHAR num[CVY_STR_SIZE];
  1575. DWORD len;
  1576. port[0] = 0;
  1577. num[0] = 0;
  1578. if (optionsp->state.port.VirtualIPAddress != CVY_ALL_VIP_NUMERIC_VALUE) {
  1579. len = CVY_STR_SIZE;
  1580. WlbsAddressToString(optionsp->state.port.VirtualIPAddress, port, &len);
  1581. (VOID) StringCchCat(port, ASIZECCH(port), L":");
  1582. }
  1583. (VOID) StringCchPrintf(num, ASIZECCH(num), L"%u", optionsp->state.port.Num);
  1584. (VOID) StringCchCat(port, ASIZECCH(port), num);
  1585. Message_print(IDS_CTR_QUERY_PORT_HDR, port);
  1586. break;
  1587. }
  1588. case filter:
  1589. {
  1590. WCHAR cltip[CVY_STR_SIZE];
  1591. WCHAR svrip[CVY_STR_SIZE];
  1592. WCHAR prot[CVY_STR_SIZE];
  1593. WCHAR flags[CVY_STR_SIZE];
  1594. DWORD len;
  1595. cltip[0] = 0;
  1596. svrip[0] = 0;
  1597. prot[0] = 0;
  1598. len = CVY_STR_SIZE;
  1599. WlbsAddressToString(optionsp->state.filter.ClientIPAddress, cltip, &len);
  1600. len = CVY_STR_SIZE;
  1601. WlbsAddressToString(optionsp->state.filter.ServerIPAddress, svrip, &len);
  1602. switch (optionsp->state.filter.Protocol) {
  1603. case TCPIP_PROTOCOL_TCP:
  1604. (VOID) StringCchCopy(prot, ASIZECCH(prot), L"TCP");
  1605. break;
  1606. case TCPIP_PROTOCOL_UDP:
  1607. (VOID) StringCchCopy(prot, ASIZECCH(prot), L"UDP");
  1608. break;
  1609. case TCPIP_PROTOCOL_IPSEC1:
  1610. (VOID) StringCchCopy(prot, ASIZECCH(prot), L"IPSec");
  1611. break;
  1612. case TCPIP_PROTOCOL_PPTP:
  1613. (VOID) StringCchCopy(prot, ASIZECCH(prot), L"PPTP");
  1614. break;
  1615. case TCPIP_PROTOCOL_GRE:
  1616. (VOID) StringCchCopy(prot, ASIZECCH(prot), L"GRE");
  1617. break;
  1618. case TCPIP_PROTOCOL_ICMP:
  1619. (VOID) StringCchCopy(prot, ASIZECCH(prot), L"ICMP");
  1620. break;
  1621. default:
  1622. (VOID) StringCchCopy(prot, ASIZECCH(prot), L"Unknown");
  1623. break;
  1624. }
  1625. ASSERT(prot[0] != 0);
  1626. if (optionsp->state.filter.Flags & NLB_FILTER_FLAGS_CONN_UP)
  1627. (VOID) StringCchCopy(flags, ASIZECCH(flags), L"SYN");
  1628. else if (optionsp->state.filter.Flags & NLB_FILTER_FLAGS_CONN_DOWN)
  1629. (VOID) StringCchCopy(flags, ASIZECCH(flags), L"FIN");
  1630. else if (optionsp->state.filter.Flags & NLB_FILTER_FLAGS_CONN_RESET)
  1631. (VOID) StringCchCopy(flags, ASIZECCH(flags), L"RST");
  1632. else
  1633. (VOID) StringCchCopy(flags, ASIZECCH(flags), L"None");
  1634. Message_print(IDS_CTR_QUERY_FILTER_HDR, cltip, optionsp->state.filter.ClientPort, svrip, optionsp->state.filter.ServerPort, prot, flags);
  1635. break;
  1636. }
  1637. default:
  1638. Message_print(IDS_CTR_QUERY_UNKNOWN);
  1639. goto end;
  1640. }
  1641. if (target_host == CVY_LOCAL_HOST) {
  1642. switch (command) {
  1643. case params:
  1644. Report_params_state(pResponse[0]);
  1645. break;
  1646. case bdateam:
  1647. Report_bda_state(pResponse[0]);
  1648. break;
  1649. case queryport:
  1650. Report_port_state(pResponse[0]);
  1651. break;
  1652. case filter:
  1653. Report_filter_state(pResponse[0]);
  1654. break;
  1655. default:
  1656. Message_print(IDS_CTR_QUERY_UNKNOWN);
  1657. goto end;
  1658. }
  1659. goto end;
  1660. }
  1661. for (i = 0; i < dwNumHosts; i++) {
  1662. if (pResponse[i].address == 0) {
  1663. Message_print(IDS_CTR_HOST_NEITHER, pResponse[i].id);
  1664. } else {
  1665. DWORD len = CVY_STR_SIZE;
  1666. WlbsAddressToString(pResponse[i].address, wbuf, &len);
  1667. Message_print(IDS_CTR_HOST_DIP_ONLY, pResponse[i].id, wbuf);
  1668. }
  1669. if (pResponse[i].status == WLBS_BAD_PASSW) {
  1670. if (target_host != CVY_ALL_HOSTS) {
  1671. WConsole(L"\n");
  1672. Message_print(IDS_CTR_BAD_PASSW);
  1673. } else {
  1674. Message_print(IDS_CTR_BAD_PASSW_C);
  1675. WConsole(L"\n");
  1676. }
  1677. continue;
  1678. }
  1679. switch (command) {
  1680. case params:
  1681. Report_params_state(pResponse[i]);
  1682. break;
  1683. case bdateam:
  1684. Report_bda_state(pResponse[i]);
  1685. break;
  1686. case queryport:
  1687. Report_port_state(pResponse[i]);
  1688. break;
  1689. case filter:
  1690. Report_filter_state(pResponse[i]);
  1691. break;
  1692. default:
  1693. Message_print(IDS_CTR_QUERY_UNKNOWN);
  1694. goto end;
  1695. }
  1696. }
  1697. end:
  1698. delete [] pResponse;
  1699. return;
  1700. }
  1701. BOOL Parse_state (INT argc, PWCHAR argv[], PINT arg_index, WLBS_COMMANDS command, PNLB_OPTIONS optionsp) {
  1702. WCHAR str[WLBS_MAX_CL_IP_ADDR + 1];
  1703. GUID guid;
  1704. HRESULT hr;
  1705. PWCHAR ptr;
  1706. ULONG len;
  1707. switch (command) {
  1708. case filter:
  1709. {
  1710. PWCHAR pPort = NULL;
  1711. if (argc < 5) return FALSE;
  1712. if (!_wcsicmp(argv[*arg_index], L"TCP"))
  1713. {
  1714. optionsp->state.filter.Protocol = TCPIP_PROTOCOL_TCP;
  1715. }
  1716. else if (!_wcsicmp(argv[*arg_index], L"UDP"))
  1717. {
  1718. optionsp->state.filter.Protocol = TCPIP_PROTOCOL_UDP;
  1719. }
  1720. else if (!_wcsicmp(argv[*arg_index], L"IPSec"))
  1721. {
  1722. optionsp->state.filter.Protocol = TCPIP_PROTOCOL_IPSEC1;
  1723. }
  1724. else if (!_wcsicmp(argv[*arg_index], L"PPTP"))
  1725. {
  1726. optionsp->state.filter.Protocol = TCPIP_PROTOCOL_PPTP;
  1727. }
  1728. else if (!_wcsicmp(argv[*arg_index], L"GRE"))
  1729. {
  1730. optionsp->state.filter.Protocol = TCPIP_PROTOCOL_GRE;
  1731. }
  1732. else if (!_wcsicmp(argv[*arg_index], L"ICMP"))
  1733. {
  1734. optionsp->state.filter.Protocol = TCPIP_PROTOCOL_ICMP;
  1735. }
  1736. else
  1737. {
  1738. return FALSE;
  1739. }
  1740. ++(*arg_index);
  1741. optionsp->state.filter.ClientPort = 0;
  1742. pPort = wcschr(argv[*arg_index], L':');
  1743. if (pPort != NULL)
  1744. {
  1745. *pPort = UNICODE_NULL;
  1746. pPort++;
  1747. optionsp->state.filter.ClientPort = (USHORT)_wtoi(pPort);
  1748. if (optionsp->state.filter.ClientPort == 0)
  1749. {
  1750. return FALSE;
  1751. }
  1752. }
  1753. if (!(optionsp->state.filter.ClientIPAddress = WlbsResolve(argv[*arg_index])))
  1754. {
  1755. return FALSE;
  1756. }
  1757. ++(*arg_index);
  1758. optionsp->state.filter.ServerPort = 0;
  1759. pPort = wcschr(argv[*arg_index], L':');
  1760. if (pPort != NULL)
  1761. {
  1762. *pPort = UNICODE_NULL;
  1763. pPort++;
  1764. optionsp->state.filter.ServerPort = (USHORT)_wtoi(pPort);
  1765. if (optionsp->state.filter.ServerPort == 0)
  1766. {
  1767. return FALSE;
  1768. }
  1769. }
  1770. if (!(optionsp->state.filter.ServerIPAddress = WlbsResolve(argv[*arg_index])))
  1771. {
  1772. return FALSE;
  1773. }
  1774. ++(*arg_index);
  1775. optionsp->state.filter.Flags = NLB_FILTER_FLAGS_CONN_DATA;
  1776. if (argc > 5)
  1777. {
  1778. if (!_wcsicmp(argv[*arg_index], L"SYN"))
  1779. {
  1780. optionsp->state.filter.Flags |= NLB_FILTER_FLAGS_CONN_UP;
  1781. ++(*arg_index);
  1782. }
  1783. else if (!_wcsicmp(argv[*arg_index], L"FIN"))
  1784. {
  1785. optionsp->state.filter.Flags |= NLB_FILTER_FLAGS_CONN_DOWN;
  1786. ++(*arg_index);
  1787. }
  1788. else if (!_wcsicmp(argv[*arg_index], L"RST"))
  1789. {
  1790. optionsp->state.filter.Flags |= NLB_FILTER_FLAGS_CONN_RESET;
  1791. ++(*arg_index);
  1792. }
  1793. }
  1794. switch (optionsp->state.filter.Protocol)
  1795. {
  1796. case TCPIP_PROTOCOL_TCP:
  1797. if (optionsp->state.filter.ServerPort == 0)
  1798. {
  1799. return FALSE;
  1800. }
  1801. if (optionsp->state.filter.ClientPort == 0)
  1802. {
  1803. if ((optionsp->state.filter.Flags == NLB_FILTER_FLAGS_CONN_DOWN) ||
  1804. (optionsp->state.filter.Flags == NLB_FILTER_FLAGS_CONN_RESET))
  1805. {
  1806. return FALSE;
  1807. }
  1808. else
  1809. {
  1810. optionsp->state.filter.Flags = NLB_FILTER_FLAGS_CONN_UP;
  1811. }
  1812. }
  1813. if (optionsp->state.filter.ServerPort != PPTP_CTRL_PORT)
  1814. {
  1815. break;
  1816. }
  1817. optionsp->state.filter.Protocol = TCPIP_PROTOCOL_PPTP;
  1818. /* This fall-through is INTENTIONAL. In this case, we're verified the TCP
  1819. parameters, but discovered that because the server port was 1723, this
  1820. is actually PPTP, so force it through the PPTP verification as well. */
  1821. case TCPIP_PROTOCOL_PPTP:
  1822. optionsp->state.filter.ServerPort = PPTP_CTRL_PORT;
  1823. if (optionsp->state.filter.ClientPort == 0)
  1824. {
  1825. if ((optionsp->state.filter.Flags == NLB_FILTER_FLAGS_CONN_DOWN) ||
  1826. (optionsp->state.filter.Flags == NLB_FILTER_FLAGS_CONN_RESET))
  1827. {
  1828. return FALSE;
  1829. }
  1830. else
  1831. {
  1832. optionsp->state.filter.Flags = NLB_FILTER_FLAGS_CONN_UP;
  1833. }
  1834. }
  1835. break;
  1836. case TCPIP_PROTOCOL_UDP:
  1837. if (optionsp->state.filter.ServerPort == 0)
  1838. {
  1839. return FALSE;
  1840. }
  1841. if ((optionsp->state.filter.ServerPort != IPSEC_CTRL_PORT) && (optionsp->state.filter.ServerPort != IPSEC_NAT_PORT))
  1842. {
  1843. if (optionsp->state.filter.Flags != NLB_FILTER_FLAGS_CONN_DATA)
  1844. {
  1845. return FALSE;
  1846. }
  1847. break;
  1848. }
  1849. optionsp->state.filter.Protocol = TCPIP_PROTOCOL_IPSEC1;
  1850. /* This fall-through is INTENTIONAL. In this case, we're verified the TCP
  1851. parameters, but discovered that because the server port was 1723, this
  1852. is actually PPTP, so force it through the PPTP verification as well. */
  1853. case TCPIP_PROTOCOL_IPSEC1:
  1854. if (optionsp->state.filter.ServerPort == 0)
  1855. {
  1856. optionsp->state.filter.ServerPort = IPSEC_CTRL_PORT;
  1857. }
  1858. if (optionsp->state.filter.ServerPort == IPSEC_CTRL_PORT)
  1859. {
  1860. if (optionsp->state.filter.ClientPort == 0)
  1861. {
  1862. optionsp->state.filter.ClientPort = IPSEC_CTRL_PORT;
  1863. }
  1864. if (optionsp->state.filter.ClientPort != IPSEC_CTRL_PORT)
  1865. {
  1866. return FALSE;
  1867. }
  1868. }
  1869. else if (optionsp->state.filter.ServerPort == IPSEC_NAT_PORT)
  1870. {
  1871. if (optionsp->state.filter.ClientPort == 0)
  1872. {
  1873. return FALSE;
  1874. }
  1875. }
  1876. else
  1877. {
  1878. return FALSE;
  1879. }
  1880. break;
  1881. case TCPIP_PROTOCOL_GRE:
  1882. if (optionsp->state.filter.Flags != NLB_FILTER_FLAGS_CONN_DATA)
  1883. {
  1884. return FALSE;
  1885. }
  1886. optionsp->state.filter.ServerPort = PPTP_CTRL_PORT;
  1887. optionsp->state.filter.ClientPort = PPTP_CTRL_PORT;
  1888. break;
  1889. case TCPIP_PROTOCOL_ICMP:
  1890. if (optionsp->state.filter.Flags != NLB_FILTER_FLAGS_CONN_DATA)
  1891. {
  1892. return FALSE;
  1893. }
  1894. optionsp->state.filter.ServerPort = 0;
  1895. optionsp->state.filter.ClientPort = 0;
  1896. break;
  1897. default:
  1898. return FALSE;
  1899. }
  1900. break;
  1901. }
  1902. case queryport:
  1903. if (argc < 3) return FALSE;
  1904. optionsp->state.port.VirtualIPAddress = CVY_ALL_VIP_NUMERIC_VALUE;
  1905. if ((ptr = wcspbrk(argv[*arg_index], L":"))) {
  1906. len = (ULONG)(ptr - argv[*arg_index]);
  1907. wcsncpy(str, argv[*arg_index], len);
  1908. str[len] = L'\0';
  1909. if (!(optionsp->state.port.VirtualIPAddress = WlbsResolve(str)))
  1910. return FALSE;
  1911. optionsp->state.port.Num = (USHORT)_wtoi(++ptr);
  1912. } else {
  1913. optionsp->state.port.Num = (USHORT)_wtoi(argv[*arg_index]);
  1914. }
  1915. ++(*arg_index);
  1916. break;
  1917. case params:
  1918. break;
  1919. case bdateam:
  1920. if (argc < 3) return FALSE;
  1921. hr = CLSIDFromString(argv[*arg_index], &guid);
  1922. if (hr != NOERROR) return FALSE;
  1923. wcsncpy(optionsp->state.bda.TeamID, argv[*arg_index], CVY_MAX_BDA_TEAM_ID);
  1924. optionsp->state.bda.TeamID[CVY_MAX_BDA_TEAM_ID] = L'\0';
  1925. ++(*arg_index);
  1926. break;
  1927. default:
  1928. return FALSE;
  1929. }
  1930. return TRUE;
  1931. }
  1932. BOOL
  1933. ParsePort(
  1934. PWCHAR arg,
  1935. PULONG pvip,
  1936. PULONG pport
  1937. )
  1938. /*
  1939. arg is expected to optionally contain a virtual IP address or a
  1940. "all", signifying the "all vip" port rule and mandatorilay contain
  1941. "all", signifying all ports, or a port number in the range of 0-65535.
  1942. Return: TRUE if valid parse, in which case *pvip & *pport contains the parsed
  1943. value. FALSE if invalid parse, in which case *pvip & *pport are undefined.
  1944. */
  1945. {
  1946. BOOL fRet = TRUE;
  1947. WCHAR vip_str[WLBS_MAX_CL_IP_ADDR+1];
  1948. WCHAR *temp_str;
  1949. ULONG port, viplen;
  1950. // Check if a vip or the "ALL" string was passed
  1951. if ((temp_str = wcspbrk(arg,L":")) != NULL)
  1952. {
  1953. viplen = (ULONG)(temp_str - arg);
  1954. wcsncpy(vip_str, arg, viplen);
  1955. vip_str[viplen] = L'\0';
  1956. *pvip = IpAddressFromAbcdWsz(vip_str);
  1957. // A vip was not passed, Check if the "All" string was passed
  1958. if (*pvip == INADDR_NONE)
  1959. {
  1960. if (_wcsicmp (vip_str, L"all") == 0)
  1961. {
  1962. *pvip = IpAddressFromAbcdWsz(CVY_DEF_ALL_VIP);
  1963. }
  1964. else
  1965. {
  1966. return FALSE;
  1967. }
  1968. }
  1969. arg = temp_str + 1;
  1970. }
  1971. else // Neither a vip nor the "All" string was passed, so this applies to every vip
  1972. {
  1973. *pvip = IOCTL_ALL_VIPS;
  1974. }
  1975. if (_wcsicmp (arg, L"all") == 0)
  1976. {
  1977. port = IOCTL_ALL_PORTS;
  1978. }
  1979. else
  1980. {
  1981. port = _wtoi (arg);
  1982. if ( wcspbrk(arg, L".:") != NULL
  1983. || (port == 0 && arg[0] != L'0')
  1984. || port > 65535
  1985. )
  1986. fRet = FALSE;
  1987. }
  1988. *pport = port;
  1989. return fRet;
  1990. }
  1991. BOOL Parse_registry (INT argc, PWCHAR argv [], PINT arg_index, PDWORD key, PDWORD value) {
  1992. if (_wcsicmp(argv[*arg_index], L"mcastipaddress") == 0) {
  1993. (*arg_index)++;
  1994. *key = mcastipaddress;
  1995. if (!(*value = WlbsResolve(argv[*arg_index])))
  1996. return FALSE;
  1997. /* The multicast IP address should be in the range of (224-239).x.x.x, but NOT (224-239).0.0.x or (224-239).128.0.x. */
  1998. if ((*value & 0xf0) != 0xe0 || (*value & 0x00ffff00) == 0 || (*value & 0x00ffff00) == 0x00008000) {
  1999. Message_print (IDS_CTR_REG_INVAL_MCASTIPADDRESS);
  2000. return FALSE;
  2001. }
  2002. (*arg_index)++;
  2003. } else if (_wcsicmp(argv[*arg_index], L"iptomcastip") == 0) {
  2004. (*arg_index)++;
  2005. *key = iptomcastip;
  2006. if (_wcsicmp(argv[*arg_index], L"on") == 0)
  2007. *value = 1;
  2008. else if (_wcsicmp(argv[*arg_index], L"off") == 0)
  2009. *value = 0;
  2010. else
  2011. return FALSE;
  2012. (*arg_index)++;
  2013. } else if (_wcsicmp(argv[*arg_index], L"masksrcmac") == 0) {
  2014. (*arg_index)++;
  2015. *key = masksrcmac;
  2016. if (_wcsicmp(argv[*arg_index], L"on") == 0)
  2017. *value = 1;
  2018. else if (_wcsicmp(argv[*arg_index], L"off") == 0)
  2019. *value = 0;
  2020. else
  2021. return FALSE;
  2022. (*arg_index)++;
  2023. } else if (_wcsicmp(argv[*arg_index], L"iptomacenable") == 0) {
  2024. (*arg_index)++;
  2025. *key = iptomacenable;
  2026. if (_wcsicmp(argv[*arg_index], L"on") == 0)
  2027. *value = 1;
  2028. else if (_wcsicmp(argv[*arg_index], L"off") == 0)
  2029. *value = 0;
  2030. else
  2031. return FALSE;
  2032. (*arg_index)++;
  2033. } else if (_wcsicmp(argv[*arg_index], L"netmonalivemsgs") == 0) {
  2034. (*arg_index)++;
  2035. *key = netmonalivemsgs;
  2036. if (_wcsicmp(argv[*arg_index], L"on") == 0)
  2037. *value = 1;
  2038. else if (_wcsicmp(argv[*arg_index], L"off") == 0)
  2039. *value = 0;
  2040. else
  2041. return FALSE;
  2042. (*arg_index)++;
  2043. } else {
  2044. Message_print(IDS_CTR_REG_KEY, argv[*arg_index]);
  2045. return FALSE;
  2046. }
  2047. return TRUE;
  2048. }
  2049. extern "C"
  2050. {
  2051. int __cdecl wmain (int argc, PWCHAR argv[]) {
  2052. int iUsageStatus = CVY_ERROR_USAGE; // Used as return status when exiting via the "usage:" path. For backward compatibility, this is not always an error path.
  2053. INT arg_index;
  2054. ULONG i, ip;
  2055. PUCHAR bp;
  2056. LONG status;
  2057. DWORD target_cl;
  2058. DWORD target_host;
  2059. WLBS_COMMANDS command = invalid;
  2060. ULONG param1 = 0;
  2061. ULONG param2 = 0;
  2062. ULONG param3 = 0;
  2063. ULONG dest_port;
  2064. PWCHAR dest_password;
  2065. DWORD dest_addr;
  2066. NLB_OPTIONS options;
  2067. DWORD operation = 0;
  2068. DWORD fdwMode = 0;
  2069. WCHAR wszCodePage[6];
  2070. //
  2071. // Set the locale for time and date
  2072. //
  2073. InitUserLocale();
  2074. //
  2075. // Set the locale for character-handling functions
  2076. //
  2077. (VOID) StringCchPrintf(wszCodePage, ASIZECCH(wszCodePage), L".4%d", GetConsoleOutputCP());
  2078. _wsetlocale(LC_CTYPE, wszCodePage);
  2079. //
  2080. // Determine whether we are writing to the console or are being redirected
  2081. //
  2082. if ((ConsoleHdl = GetStdHandle(STD_OUTPUT_HANDLE)) == INVALID_HANDLE_VALUE)
  2083. {
  2084. wprintf(L"GetStdHandle failed, Unable to write to Console !!!\n");
  2085. return CVY_ERROR_SYSTEM;
  2086. }
  2087. g_fOutToConsole = TRUE;
  2088. if( !(GetFileType(ConsoleHdl) & FILE_TYPE_CHAR) ||
  2089. !GetConsoleMode( ConsoleHdl, &fdwMode) )
  2090. {
  2091. g_fOutToConsole = FALSE;
  2092. }
  2093. Message_print(IDS_CTR_NAME, CVY_NAME, CVY_VERSION);
  2094. if (argc < 2) {
  2095. usage:
  2096. Message_print(IDS_CTR_USAGE, CVY_NAME);
  2097. Message_print(IDS_CTR_USAGE2);
  2098. Message_print(IDS_CTR_USAGE3);
  2099. Message_print(IDS_CTR_USAGE4);
  2100. return iUsageStatus;
  2101. }
  2102. status = WlbsInit(NULL, WLBS_API_VER, NULL);
  2103. if (status == WLBS_INIT_ERROR) {
  2104. Message_print(IDS_CTR_WSOCK);
  2105. Error_print(TRUE);
  2106. return CVY_ERROR_SYSTEM;
  2107. }
  2108. arg_index = 1;
  2109. ZeroMemory((PVOID)&options, sizeof(NLB_OPTIONS));
  2110. /* parse command */
  2111. if (_wcsicmp(argv [arg_index], L"ip2mac") == 0) {
  2112. command = ip2mac;
  2113. arg_index++;
  2114. if (argc < 3)
  2115. goto usage;
  2116. ip = WlbsResolve(argv[arg_index]);
  2117. bp = (PUCHAR)(&ip);
  2118. Message_print(IDS_CTR_IP, inet_ntoa(*((struct in_addr *)&ip)));
  2119. Message_print(IDS_CTR_UCAST, bp[0], bp[1], bp[2], bp[3]);
  2120. Message_print(IDS_CTR_MCAST, bp[0], bp[1], bp[2], bp[3]);
  2121. Message_print(IDS_CTR_IGMP_MCAST, bp[2], bp[3]);
  2122. return CVY_OK;
  2123. } else if (_wcsicmp(argv[arg_index], L"help") == 0) {
  2124. iUsageStatus = CVY_OK;
  2125. goto usage;
  2126. } else if (_wcsicmp(argv[arg_index], L"suspend") == 0) {
  2127. command = suspend;
  2128. arg_index++;
  2129. #ifndef BACKWARD_COMPATIBILITY
  2130. if (argc < 3)
  2131. goto usage;
  2132. #endif
  2133. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2134. goto usage;
  2135. } else if (_wcsicmp(argv[arg_index], L"resume") == 0) {
  2136. command = resume;
  2137. arg_index++;
  2138. #ifndef BACKWARD_COMPATIBILITY
  2139. if (argc < 3)
  2140. goto usage;
  2141. #endif
  2142. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2143. goto usage;
  2144. } else if (_wcsicmp(argv[arg_index], L"start") == 0) {
  2145. command = __start;
  2146. arg_index++;
  2147. #ifndef BACKWARD_COMPATIBILITY
  2148. if (argc < 3)
  2149. goto usage;
  2150. #endif
  2151. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2152. goto usage;
  2153. } else if (_wcsicmp(argv[arg_index], L"stop") == 0) {
  2154. command = stop;
  2155. arg_index++;
  2156. #ifndef BACKWARD_COMPATIBILITY
  2157. if (argc < 3)
  2158. goto usage;
  2159. #endif
  2160. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2161. goto usage;
  2162. } else if (_wcsicmp(argv[arg_index], L"drainstop") == 0) {
  2163. command = drainstop;
  2164. arg_index++;
  2165. #ifndef BACKWARD_COMPATIBILITY
  2166. if (argc < 3)
  2167. goto usage;
  2168. #endif
  2169. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2170. goto usage;
  2171. } else if (_wcsicmp(argv[arg_index], L"query") == 0) {
  2172. command = query;
  2173. arg_index++;
  2174. #ifndef BACKWARD_COMPATIBILITY
  2175. if (argc < 3)
  2176. goto usage;
  2177. #endif
  2178. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2179. goto usage;
  2180. } else if (_wcsicmp(argv[arg_index], L"enable") == 0) {
  2181. command = enable;
  2182. arg_index++;
  2183. #ifdef BACKWARD_COMPATIBILITY
  2184. if (argc < 3)
  2185. #else
  2186. if (argc < 4)
  2187. #endif
  2188. goto usage;
  2189. if (!ParsePort(argv[arg_index], &param1, &param2))
  2190. goto usage;
  2191. arg_index++;
  2192. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2193. goto usage;
  2194. } else if (_wcsicmp(argv[arg_index], L"disable") == 0) {
  2195. command = disable;
  2196. arg_index++;
  2197. #ifdef BACKWARD_COMPATIBILITY
  2198. if (argc < 3)
  2199. #else
  2200. if (argc < 4)
  2201. #endif
  2202. goto usage;
  2203. if (!ParsePort(argv[arg_index], &param1, &param2))
  2204. goto usage;
  2205. arg_index++;
  2206. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2207. goto usage;
  2208. } else if (_wcsicmp(argv[arg_index], L"drain") == 0) {
  2209. command = drain;
  2210. arg_index++;
  2211. #ifdef BACKWARD_COMPATIBILITY
  2212. if (argc < 3)
  2213. #else
  2214. if (argc < 4)
  2215. #endif
  2216. goto usage;
  2217. if (!ParsePort(argv[arg_index], &param1, &param2))
  2218. goto usage;
  2219. arg_index++;
  2220. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2221. goto usage;
  2222. }
  2223. /* local only commands */
  2224. else if (_wcsicmp(argv[arg_index], L"display") == 0) {
  2225. command = display;
  2226. arg_index++;
  2227. target_host = CVY_LOCAL_HOST;
  2228. // Verify that the cluster ip or "All" string is passed and there are no more arguments
  2229. if ((arg_index == argc) || (arg_index + 1 < argc))
  2230. #ifdef BACKWARD_COMPATIBILITY
  2231. if (arg_index == argc)
  2232. target_cl = CVY_ALL_CLUSTERS;
  2233. else
  2234. goto usage;
  2235. #else
  2236. goto usage;
  2237. #endif
  2238. else {
  2239. // Retrieve the Cluster IP Address or "ALL"
  2240. if (_wcsicmp (argv[arg_index], L"all") == 0)
  2241. {
  2242. target_cl = CVY_ALL_CLUSTERS;
  2243. }
  2244. else
  2245. {
  2246. target_cl = WlbsResolve(argv [arg_index]);
  2247. if (target_cl == 0)
  2248. goto usage;
  2249. }
  2250. arg_index++;
  2251. }
  2252. } else if (_wcsicmp(argv[arg_index], L"reload") == 0) {
  2253. command = reload;
  2254. arg_index++;
  2255. target_host = CVY_LOCAL_HOST;
  2256. // Verify that the cluster ip or "All" string is passed and there are no more arguments
  2257. if ((arg_index == argc) || (arg_index + 1 < argc))
  2258. #ifdef BACKWARD_COMPATIBILITY
  2259. if (arg_index == argc)
  2260. target_cl = CVY_ALL_CLUSTERS;
  2261. else
  2262. goto usage;
  2263. #else
  2264. goto usage;
  2265. #endif
  2266. else {
  2267. // Retrieve the Cluster IP Address or "ALL"
  2268. if (_wcsicmp (argv[arg_index], L"all") == 0)
  2269. {
  2270. target_cl = CVY_ALL_CLUSTERS;
  2271. }
  2272. else
  2273. {
  2274. target_cl = WlbsResolve(argv [arg_index]);
  2275. if (target_cl == 0)
  2276. goto usage;
  2277. }
  2278. arg_index++;
  2279. }
  2280. }
  2281. else if (_wcsicmp(argv[arg_index], L"registry") == 0)
  2282. {
  2283. command = registry;
  2284. param3 = FALSE;
  2285. arg_index++;
  2286. if (argc < 4)
  2287. goto reg_usage;
  2288. if (!Parse_registry(argc, argv, &arg_index, &param1, &param2))
  2289. goto reg_usage;
  2290. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2291. goto reg_usage;
  2292. /* Force local operation. */
  2293. target_host = CVY_LOCAL_HOST;
  2294. }
  2295. else if (_wcsicmp(argv[arg_index], L"filter") == 0)
  2296. {
  2297. command = filter;
  2298. arg_index++;
  2299. if (!Parse_state(argc, argv, &arg_index, command, &options))
  2300. goto filter_usage;
  2301. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2302. goto filter_usage;
  2303. }
  2304. else if (_wcsicmp(argv[arg_index], L"params") == 0)
  2305. {
  2306. command = params;
  2307. arg_index++;
  2308. if (!Parse_state(argc, argv, &arg_index, command, &options))
  2309. goto usage;
  2310. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2311. goto usage;
  2312. /* Force local operation. */
  2313. target_host = CVY_LOCAL_HOST;
  2314. }
  2315. else if (_wcsicmp(argv[arg_index], L"queryport") == 0)
  2316. {
  2317. command = queryport;
  2318. arg_index++;
  2319. if (!Parse_state(argc, argv, &arg_index, command, &options))
  2320. goto usage;
  2321. if (!Parse(argc, argv, &arg_index, &target_cl, &target_host))
  2322. goto usage;
  2323. }
  2324. else if (_wcsicmp(argv[arg_index], L"bdateam") == 0)
  2325. {
  2326. command = bdateam;
  2327. arg_index++;
  2328. if (!Parse_state(argc, argv, &arg_index, command, &options))
  2329. goto bdateam_usage;
  2330. /* Force local operation across ALL clusters - this operation is
  2331. actually global and not specific to any one cluster, so we
  2332. operate on ANY one cluster (in a loop, below) and bail out. */
  2333. target_cl = CVY_ALL_CLUSTERS;
  2334. target_host = CVY_LOCAL_HOST;
  2335. }
  2336. else
  2337. goto usage;
  2338. /* The remote control parameters need to be parsed. */
  2339. dest_password = NULL;
  2340. dest_addr = 0;
  2341. dest_port = 0;
  2342. while (arg_index < argc) {
  2343. if (argv[arg_index][0] == L'/' || argv[arg_index][0] == L'-') {
  2344. if (_wcsicmp(argv[arg_index] + 1, L"PASSW") == 0) {
  2345. arg_index++;
  2346. if (arg_index >= argc || argv[arg_index][0] == L'/' || argv[arg_index][0] == L'-') {
  2347. HANDLE hConsole;
  2348. DWORD dwMode; // console mode
  2349. DWORD dwInputMode; // stdin input mode
  2350. Message_print(IDS_CTR_PASSW);
  2351. hConsole = GetStdHandle(STD_INPUT_HANDLE);
  2352. dwInputMode = GetFileType(hConsole);
  2353. //
  2354. // prompt for password, making sure password isn't echoed
  2355. // if the stdin is redirected, don't bother querying/changing console mode
  2356. //
  2357. if (dwInputMode == FILE_TYPE_CHAR) {
  2358. if (!GetConsoleMode(hConsole, &dwMode)) {
  2359. Error_print(FALSE);
  2360. return CVY_ERROR_SYSTEM;
  2361. }
  2362. if (!SetConsoleMode(hConsole, dwMode &= ~ENABLE_ECHO_INPUT)) {
  2363. Error_print(FALSE);
  2364. return CVY_ERROR_SYSTEM;
  2365. }
  2366. }
  2367. for (i = 0; i < CVY_STR_SIZE - 1; i++) {
  2368. //
  2369. // read a character, copying to the buffer
  2370. // break out of loop on CR and EOF
  2371. //
  2372. if ((psw_buf[i] = fgetwc(stdin)) == WEOF)
  2373. break;
  2374. if (psw_buf[i] == L'\n')
  2375. break;
  2376. }
  2377. // NULL terminate the password
  2378. psw_buf[i] = L'\0';
  2379. // restore previous console mode
  2380. if (dwInputMode == FILE_TYPE_CHAR)
  2381. SetConsoleMode(hConsole, dwMode);
  2382. WConsole(L"\n");
  2383. if (i == 0)
  2384. dest_password = NULL;
  2385. else
  2386. dest_password = psw_buf;
  2387. } else {
  2388. dest_password = argv[arg_index];
  2389. arg_index ++;
  2390. }
  2391. } else if (_wcsicmp(argv[arg_index] + 1, L"PORT") == 0) {
  2392. arg_index++;
  2393. if (arg_index >= argc || argv[arg_index][0] == L'/' || argv[arg_index][0] == L'-')
  2394. goto usage;
  2395. dest_port = (USHORT)_wtoi(argv[arg_index]);
  2396. if (dest_port == 0)
  2397. goto usage;
  2398. arg_index++;
  2399. } else if (_wcsicmp(argv[arg_index] + 1, L"DEST") == 0) {
  2400. arg_index++;
  2401. if (arg_index >= argc || argv[arg_index][0] == L'/' || argv[arg_index][0] == L'-')
  2402. goto usage;
  2403. dest_addr = WlbsResolve(argv [arg_index]);
  2404. if (dest_addr == 0)
  2405. goto usage;
  2406. arg_index++;
  2407. } else if (_wcsicmp(argv[arg_index] + 1, L"commit") == 0) {
  2408. arg_index++;
  2409. param3 = TRUE;
  2410. } else
  2411. goto usage;
  2412. } else
  2413. goto usage;
  2414. }
  2415. if (target_cl != CVY_ALL_CLUSTERS) {
  2416. switch (command) {
  2417. case params:
  2418. case filter:
  2419. case bdateam:
  2420. case queryport:
  2421. Process_state(command, target_cl, target_host, &options, dest_port, dest_password);
  2422. break;
  2423. default:
  2424. Process(command, target_cl, target_host, param1, param2, param3, dest_port, dest_addr, dest_password);
  2425. break;
  2426. }
  2427. return CVY_OK;
  2428. }
  2429. /* Enumerate all the clusters and call process for each one of them */
  2430. else {
  2431. DWORD clusters[CVY_MAX_ADAPTERS];
  2432. DWORD len;
  2433. len = CVY_MAX_ADAPTERS;
  2434. WlbsEnumClusters(clusters, &len);
  2435. if (!len) {
  2436. Message_print(IDS_CTR_NO_CVY, CVY_NAME);
  2437. return CVY_OK;
  2438. }
  2439. for (i = 0 ; i < len; i++) {
  2440. DWORD buflen = CVY_STR_SIZE;
  2441. switch (command) {
  2442. case bdateam:
  2443. /* If this is a BDA teaming operation, then call process once and break out of this loop. This is a trick
  2444. for retrieving BDA teaming state, which is global, which means that we can call this IOCTL on ANY cluster
  2445. instance, but we don't need to apply it to all of them - so call it the first one, and break out. */
  2446. Process_state(command, clusters[i], target_host, &options, dest_port, dest_password);
  2447. return CVY_OK;
  2448. case params:
  2449. case filter:
  2450. case queryport:
  2451. WlbsAddressToString(clusters[i], wbuf, &buflen);
  2452. Message_print(IDS_CTR_CLUSTER_ID, wbuf);
  2453. Process_state(command, clusters[i], target_host, &options, dest_port, dest_password);
  2454. break;
  2455. default:
  2456. WlbsAddressToString(clusters[i], wbuf, &buflen);
  2457. Message_print(IDS_CTR_CLUSTER_ID, wbuf);
  2458. Process(command, clusters[i], target_host, param1, param2, param3, dest_port, dest_addr, dest_password);
  2459. break;
  2460. }
  2461. if (i < len - 1)
  2462. WConsole (L"\n");
  2463. }
  2464. return CVY_OK;
  2465. }
  2466. reg_usage:
  2467. Message_print(IDS_CTR_REG_USAGE, CVY_NAME);
  2468. return CVY_ERROR_USAGE;
  2469. filter_usage:
  2470. Message_print(IDS_CTR_FILTER_USAGE1, CVY_NAME);
  2471. Message_print(IDS_CTR_FILTER_USAGE2);
  2472. return CVY_ERROR_USAGE;
  2473. bdateam_usage:
  2474. Message_print(IDS_CTR_BDA_TEAMING_USAGE, CVY_NAME);
  2475. return CVY_ERROR_USAGE;
  2476. }
  2477. }