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.

738 lines
26 KiB

  1. //***************************************************************************
  2. // WLBSPRIVATE.CPP
  3. //
  4. //
  5. // Module: WMI Framework Instance provider
  6. //
  7. // Purpose: Contains routines that access the private fields of
  8. // WLBS_REG_PARAMS
  9. //
  10. // Copyright (c)2001 Microsoft Corporation, All Rights Reserved
  11. //
  12. // History:
  13. //
  14. // 10/13/01 JosephJ Created (moved MyWlbsXXX functions from cfutil.cpp)
  15. //
  16. //***************************************************************************
  17. //
  18. // This macro allows us to access the private fields of WLBS_REG_PARAMS
  19. //
  20. #define WLBSAPI_INTERNAL_ONLY
  21. #include "private.h"
  22. VOID
  23. CfgUtilSetHashedRemoteControlPassword(
  24. IN OUT WLBS_REG_PARAMS *pParams,
  25. IN DWORD dwHashedPassword
  26. )
  27. {
  28. pParams->i_rct_password = dwHashedPassword;
  29. }
  30. DWORD
  31. CfgUtilGetHashedRemoteControlPassword(
  32. IN const WLBS_REG_PARAMS *pParams
  33. )
  34. {
  35. return pParams->i_rct_password;
  36. }
  37. //
  38. // Following (MyXXX) functions are to be used only on systems
  39. // that do not have wlbsctrl.dll installed.
  40. //
  41. DWORD MyWlbsSetDefaults(PWLBS_REG_PARAMS reg_data)
  42. {
  43. reg_data -> install_date = 0;
  44. reg_data -> i_verify_date = 0;
  45. // reg_data -> cluster_nic_name [0] = _TEXT('\0');
  46. reg_data -> i_parms_ver = CVY_DEF_VERSION;
  47. reg_data -> i_virtual_nic_name [0] = _TEXT('\0');
  48. reg_data -> host_priority = CVY_DEF_HOST_PRIORITY;
  49. reg_data -> cluster_mode = CVY_DEF_CLUSTER_MODE;
  50. reg_data -> persisted_states = CVY_DEF_PERSISTED_STATES;
  51. ARRAYSTRCPY (reg_data -> cl_mac_addr, CVY_DEF_NETWORK_ADDR);
  52. ARRAYSTRCPY (reg_data -> cl_ip_addr, CVY_DEF_CL_IP_ADDR);
  53. ARRAYSTRCPY (reg_data -> cl_net_mask, CVY_DEF_CL_NET_MASK);
  54. ARRAYSTRCPY (reg_data -> ded_ip_addr, CVY_DEF_DED_IP_ADDR);
  55. ARRAYSTRCPY (reg_data -> ded_net_mask, CVY_DEF_DED_NET_MASK);
  56. ARRAYSTRCPY (reg_data -> domain_name, CVY_DEF_DOMAIN_NAME);
  57. reg_data -> alive_period = CVY_DEF_ALIVE_PERIOD;
  58. reg_data -> alive_tolerance = CVY_DEF_ALIVE_TOLER;
  59. reg_data -> num_actions = CVY_DEF_NUM_ACTIONS;
  60. reg_data -> num_packets = CVY_DEF_NUM_PACKETS;
  61. reg_data -> num_send_msgs = CVY_DEF_NUM_SEND_MSGS;
  62. reg_data -> dscr_per_alloc = CVY_DEF_DSCR_PER_ALLOC;
  63. reg_data -> max_dscr_allocs = CVY_DEF_MAX_DSCR_ALLOCS;
  64. reg_data -> i_scale_client = CVY_DEF_SCALE_CLIENT;
  65. reg_data -> i_cleanup_delay = CVY_DEF_CLEANUP_DELAY;
  66. reg_data -> i_ip_chg_delay = CVY_DEF_IP_CHG_DELAY;
  67. reg_data -> i_nbt_support = CVY_DEF_NBT_SUPPORT;
  68. reg_data -> mcast_support = CVY_DEF_MCAST_SUPPORT;
  69. reg_data -> i_mcast_spoof = CVY_DEF_MCAST_SPOOF;
  70. reg_data -> mask_src_mac = CVY_DEF_MASK_SRC_MAC;
  71. reg_data -> i_netmon_alive = CVY_DEF_NETMON_ALIVE;
  72. reg_data -> i_effective_version = CVY_NT40_VERSION_FULL;
  73. reg_data -> i_convert_mac = CVY_DEF_CONVERT_MAC;
  74. reg_data -> i_num_rules = 0;
  75. memset (reg_data -> i_port_rules, 0, sizeof (WLBS_PORT_RULE) * WLBS_MAX_RULES);
  76. ARRAYSTRCPY (reg_data -> i_license_key, CVY_DEF_LICENSE_KEY);
  77. reg_data -> i_rmt_password = CVY_DEF_RMT_PASSWORD;
  78. reg_data -> i_rct_password = CVY_DEF_RCT_PASSWORD;
  79. reg_data -> rct_port = CVY_DEF_RCT_PORT;
  80. reg_data -> rct_enabled = CVY_DEF_RCT_ENABLED;
  81. reg_data -> i_max_hosts = CVY_MAX_HOSTS;
  82. reg_data -> i_max_rules = CVY_MAX_USABLE_RULES;
  83. reg_data -> fIGMPSupport = CVY_DEF_IGMP_SUPPORT;
  84. ARRAYSTRCPY(reg_data -> szMCastIpAddress, CVY_DEF_MCAST_IP_ADDR);
  85. reg_data -> fIpToMCastIp = CVY_DEF_IP_TO_MCASTIP;
  86. reg_data->bda_teaming.active = CVY_DEF_BDA_ACTIVE;
  87. reg_data->bda_teaming.master = CVY_DEF_BDA_MASTER;
  88. reg_data->bda_teaming.reverse_hash = CVY_DEF_BDA_REVERSE_HASH;
  89. reg_data->bda_teaming.team_id[0] = CVY_DEF_BDA_TEAM_ID;
  90. reg_data -> i_num_rules = 1;
  91. // fill in the first port rule.
  92. ARRAYSTRCPY(
  93. reg_data->i_port_rules[0].virtual_ip_addr,
  94. CVY_DEF_ALL_VIP
  95. );
  96. reg_data -> i_port_rules [0] . start_port = CVY_DEF_PORT_START;
  97. reg_data -> i_port_rules [0] . end_port = CVY_DEF_PORT_END;
  98. reg_data -> i_port_rules [0] . valid = TRUE;
  99. reg_data -> i_port_rules [0] . mode = CVY_DEF_MODE;
  100. reg_data -> i_port_rules [0] . mode_data . multi . equal_load = TRUE;
  101. reg_data -> i_port_rules [0] . mode_data . multi . affinity = CVY_DEF_AFFINITY;
  102. reg_data -> i_port_rules [0] . mode_data . multi . load = CVY_DEF_LOAD;
  103. reg_data -> i_port_rules [0] . protocol = CVY_DEF_PROTOCOL;
  104. CVY_RULE_CODE_SET(& reg_data -> i_port_rules [0]);
  105. return WLBS_OK;
  106. }
  107. DWORD MyWlbsEnumPortRules
  108. (
  109. const PWLBS_REG_PARAMS reg_data,
  110. PWLBS_PORT_RULE rules,
  111. PDWORD num_rules
  112. )
  113. {
  114. DWORD count_rules, i, index;
  115. DWORD lowest_vip, lowest_port;
  116. BOOL array_flags [WLBS_MAX_RULES];
  117. WLBS_PORT_RULE sorted_rules [WLBS_MAX_RULES];
  118. if ((reg_data == NULL) || (num_rules == NULL))
  119. {
  120. return WLBS_BAD_PARAMS;
  121. }
  122. if (*num_rules == 0)
  123. rules = NULL;
  124. /* this array is used for keeping track of which rules have already been retrieved */
  125. /* This is needed since the rules are to be retrieved in the sorted order */
  126. memset ( array_flags, 0, sizeof(BOOL) * WLBS_MAX_RULES );
  127. count_rules = 0;
  128. while ((count_rules < *num_rules) && (count_rules < reg_data -> i_num_rules))
  129. {
  130. i = 0;
  131. /* find the first rule that has not been retrieved */
  132. while ((! reg_data -> i_port_rules [i] . valid) || array_flags [i])
  133. {
  134. i++;
  135. }
  136. lowest_vip = htonl(IpAddressFromAbcdWsz(reg_data -> i_port_rules [i] . virtual_ip_addr));
  137. lowest_port = reg_data -> i_port_rules [i] . start_port;
  138. index = i;
  139. /* Compare that rule with the other non-retrieved rules to get the rule with the
  140. lowest VIP & start_port */
  141. i++;
  142. while (i < WLBS_MAX_RULES)
  143. {
  144. if (reg_data -> i_port_rules [i] . valid && ( ! array_flags [i] ))
  145. {
  146. DWORD current_vip = htonl(IpAddressFromAbcdWsz(reg_data -> i_port_rules [i] . virtual_ip_addr));
  147. if ((current_vip < lowest_vip)
  148. || ((current_vip == lowest_vip) && (reg_data -> i_port_rules [i] . start_port < lowest_port)))
  149. {
  150. lowest_vip = current_vip;
  151. lowest_port = reg_data -> i_port_rules [i] . start_port;
  152. index = i;
  153. }
  154. }
  155. i++;
  156. }
  157. /* The array_flags [i] element is set to TRUE if the rule is retrieved */
  158. array_flags [index] = TRUE;
  159. sorted_rules [count_rules] = reg_data -> i_port_rules [index];
  160. count_rules ++;
  161. }
  162. /* write the sorted rules back into the return array */
  163. for (i = 0; i < count_rules; i++)
  164. {
  165. rules[i] = sorted_rules[i];
  166. }
  167. /* invalidate the remaining rules in the buffer */
  168. for (i = count_rules; i < *num_rules; i++)
  169. rules [i] . valid = FALSE;
  170. if (*num_rules < reg_data -> i_num_rules)
  171. {
  172. *num_rules = reg_data -> i_num_rules;
  173. return WLBS_TRUNCATED;
  174. }
  175. *num_rules = reg_data -> i_num_rules;
  176. return WLBS_OK;
  177. } /* end WlbsEnumPortRules */
  178. VOID MyWlbsDeleteAllPortRules
  179. (
  180. PWLBS_REG_PARAMS reg_data
  181. )
  182. {
  183. reg_data -> i_num_rules = 0;
  184. ZeroMemory(reg_data -> i_port_rules, sizeof(reg_data -> i_port_rules));
  185. } /* end WlbsDeleteAllPortRules */
  186. DWORD MyWlbsAddPortRule
  187. (
  188. PWLBS_REG_PARAMS reg_data,
  189. const PWLBS_PORT_RULE rule
  190. )
  191. {
  192. int i;
  193. DWORD vip;
  194. if ((reg_data == NULL) || (rule == NULL))
  195. {
  196. return WLBS_BAD_PARAMS;
  197. }
  198. /* Check if there is space for the new rule */
  199. if (reg_data -> i_num_rules == WLBS_MAX_RULES)
  200. {
  201. return WLBS_MAX_PORT_RULES;
  202. }
  203. /* check the rule for valid values */
  204. /* check for non-zero vip and conflict with dip */
  205. vip = IpAddressFromAbcdWsz(rule -> virtual_ip_addr);
  206. if (vip == 0 || (INADDR_NONE == vip && lstrcmpi(rule -> virtual_ip_addr, CVY_DEF_ALL_VIP) != 0))
  207. {
  208. return WLBS_BAD_PORT_PARAMS;
  209. }
  210. if (vip == IpAddressFromAbcdWsz(reg_data->ded_ip_addr))
  211. {
  212. return WLBS_BAD_PORT_PARAMS;
  213. }
  214. /* first check the range of the start and end ports */
  215. if ((rule -> start_port > rule -> end_port) ||
  216. // CLEAN_64BIT (rule -> start_port < CVY_MIN_PORT) ||
  217. (rule -> end_port > CVY_MAX_PORT))
  218. {
  219. return WLBS_BAD_PORT_PARAMS;
  220. }
  221. /* check the protocol range */
  222. if ((rule -> protocol < CVY_MIN_PROTOCOL) || (rule -> protocol > CVY_MAX_PROTOCOL))
  223. {
  224. return WLBS_BAD_PORT_PARAMS;
  225. }
  226. /* check filtering mode to see whether it is within range */
  227. if ((rule -> mode < CVY_MIN_MODE) || (rule -> mode > CVY_MAX_MODE))
  228. {
  229. return WLBS_BAD_PORT_PARAMS;
  230. }
  231. /* check load weight and affinity if multiple hosts */
  232. if (rule -> mode == CVY_MULTI)
  233. {
  234. if ((rule -> mode_data . multi . affinity < CVY_MIN_AFFINITY) ||
  235. (rule -> mode_data . multi . affinity > CVY_MAX_AFFINITY))
  236. {
  237. return WLBS_BAD_PORT_PARAMS;
  238. }
  239. if ((rule -> mode_data . multi . equal_load < CVY_MIN_EQUAL_LOAD) ||
  240. (rule -> mode_data . multi . equal_load > CVY_MAX_EQUAL_LOAD))
  241. {
  242. return WLBS_BAD_PORT_PARAMS;
  243. }
  244. if (! rule -> mode_data . multi . equal_load)
  245. {
  246. if ((rule -> mode_data . multi . load > CVY_MAX_LOAD))
  247. //CLEAN_64BIT (rule -> mode_data . multi . load < CVY_MIN_LOAD) ||
  248. {
  249. return WLBS_BAD_PORT_PARAMS;
  250. }
  251. }
  252. }
  253. /* check handling priority range if single host */
  254. if (rule -> mode == CVY_SINGLE)
  255. {
  256. if ((rule -> mode_data . single . priority < CVY_MIN_PRIORITY) ||
  257. (rule -> mode_data . single . priority > CVY_MAX_PRIORITY))
  258. {
  259. return WLBS_BAD_PORT_PARAMS;
  260. }
  261. }
  262. /* go through the rule list and then check for overlapping conditions */
  263. for (i = 0; i < WLBS_MAX_RULES; i++)
  264. {
  265. if (reg_data -> i_port_rules[i] . valid == TRUE)
  266. {
  267. if ((IpAddressFromAbcdWsz(reg_data -> i_port_rules[i] . virtual_ip_addr) == vip)
  268. && (( (reg_data -> i_port_rules[i] . start_port <= rule -> start_port) &&
  269. (reg_data -> i_port_rules[i] . end_port >= rule -> start_port)) ||
  270. ( (reg_data -> i_port_rules[i] . start_port >= rule -> start_port) &&
  271. (reg_data -> i_port_rules[i] . start_port <= rule -> end_port))))
  272. {
  273. return WLBS_PORT_OVERLAP;
  274. }
  275. }
  276. }
  277. /* go through the rule list and find out the first empty spot
  278. and write out the port rule */
  279. for (i = 0 ; i < WLBS_MAX_RULES ; i++)
  280. {
  281. if (reg_data -> i_port_rules[i] . valid == FALSE)
  282. {
  283. reg_data -> i_num_rules ++ ;
  284. reg_data -> i_port_rules [i] = *rule;
  285. reg_data -> i_port_rules [i] . valid = TRUE;
  286. CVY_RULE_CODE_SET(& reg_data -> i_port_rules [i]);
  287. return WLBS_OK;
  288. }
  289. }
  290. return WLBS_MAX_PORT_RULES;
  291. } /* end WlbsAddPortRule */
  292. BOOL MyWlbsValidateParams(
  293. const PWLBS_REG_PARAMS paramp
  294. )
  295. {
  296. // Following stolen from wlbs\api
  297. #define WLBS_FIELD_LOW 0
  298. #define WLBS_FIELD_HIGH 255
  299. #define WLBS_IP_FIELD_ZERO_LOW 1
  300. #define WLBS_IP_FIELD_ZERO_HIGH 223
  301. bool fRet = FALSE;
  302. DWORD idx;
  303. IN_ADDR dwIPAddr;
  304. CHAR * szIPAddr;
  305. DWORD num_rules;
  306. WLBS_PORT_RULE *port_rule;
  307. /* verify and if necessary reset the parameters */
  308. //
  309. // We don't validate the lower bound for unsigned words when the lower bound is 0. Otherwise we
  310. // get a compiler warning, promoted to an error, because such a test can't fail
  311. //
  312. // Ignore lower bound checking
  313. //
  314. CVY_CHECK_MAX (paramp -> i_scale_client, CVY_MAX_SCALE_CLIENT);
  315. CVY_CHECK_MAX (paramp -> i_nbt_support, CVY_MAX_NBT_SUPPORT);
  316. CVY_CHECK_MAX (paramp -> mcast_support, CVY_MAX_MCAST_SUPPORT);
  317. CVY_CHECK_MAX (paramp -> i_mcast_spoof, CVY_MAX_MCAST_SPOOF);
  318. CVY_CHECK_MAX (paramp -> mask_src_mac, CVY_MAX_MASK_SRC_MAC);
  319. CVY_CHECK_MAX (paramp -> i_netmon_alive, CVY_MAX_NETMON_ALIVE);
  320. CVY_CHECK_MAX (paramp -> i_convert_mac, CVY_MAX_CONVERT_MAC);
  321. CVY_CHECK_MAX (paramp -> rct_port, CVY_MAX_RCT_PORT);
  322. CVY_CHECK_MAX (paramp -> rct_enabled, CVY_MAX_RCT_ENABLED);
  323. CVY_CHECK_MAX (paramp -> i_cleanup_delay, CVY_MAX_CLEANUP_DELAY);
  324. CVY_CHECK_MAX (paramp -> i_ip_chg_delay, CVY_MAX_IP_CHG_DELAY);
  325. CVY_CHECK_MAX (paramp -> i_num_rules, CVY_MAX_NUM_RULES);
  326. CVY_CHECK_MAX (paramp -> cluster_mode, CVY_MAX_CLUSTER_MODE);
  327. //
  328. // End Ignore lower bound checking
  329. //
  330. //
  331. // CVY_NAME_VERSION is not validated since its value is used and manipulated before we get here
  332. // CVY_NAME_LICENSE_KEY is not validated since it can take any value.
  333. // RMT_PASSWORD is not validated since it can take any storable value
  334. // RCT_PASSWORD is not validated since it can take any storable value
  335. // CVY_NAME_IGMP_SUPPORT is not validated because it is of BOOL type and can thus take any value
  336. // CVY_NAME_IP_TO_MCASTIP is not validated because it is of BOOL type and can thus take any value
  337. //
  338. CVY_CHECK_MIN (paramp -> alive_period, CVY_MIN_ALIVE_PERIOD);
  339. CVY_CHECK_MAX (paramp -> alive_period, CVY_MAX_ALIVE_PERIOD);
  340. CVY_CHECK_MIN (paramp -> alive_tolerance, CVY_MIN_ALIVE_TOLER);
  341. CVY_CHECK_MAX (paramp -> alive_tolerance, CVY_MAX_ALIVE_TOLER);
  342. CVY_CHECK_MIN (paramp -> num_actions, CVY_MIN_NUM_ACTIONS);
  343. CVY_CHECK_MAX (paramp -> num_actions, CVY_MAX_NUM_ACTIONS);
  344. CVY_CHECK_MIN (paramp -> num_packets, CVY_MIN_NUM_PACKETS);
  345. CVY_CHECK_MAX (paramp -> num_packets, CVY_MAX_NUM_PACKETS);
  346. CVY_CHECK_MIN (paramp -> dscr_per_alloc, CVY_MIN_DSCR_PER_ALLOC);
  347. CVY_CHECK_MAX (paramp -> dscr_per_alloc, CVY_MAX_DSCR_PER_ALLOC);
  348. CVY_CHECK_MIN (paramp -> max_dscr_allocs, CVY_MIN_MAX_DSCR_ALLOCS);
  349. CVY_CHECK_MAX (paramp -> max_dscr_allocs, CVY_MAX_MAX_DSCR_ALLOCS);
  350. CVY_CHECK_MIN (paramp -> num_send_msgs, (paramp -> i_max_hosts + 1) * 2);
  351. CVY_CHECK_MAX (paramp -> num_send_msgs, (paramp -> i_max_hosts + 1) * 10);
  352. CVY_CHECK_MIN (paramp -> host_priority, CVY_MIN_HOST_PRIORITY);
  353. CVY_CHECK_MAX (paramp -> host_priority, CVY_MAX_HOST_PRIORITY);
  354. /* If the cluster IP address is not 0.0.0.0, then make sure the IP address is valid. */
  355. if (lstrcmpi(paramp->cl_ip_addr, CVY_DEF_CL_IP_ADDR)) {
  356. /* Check the validity of the IP address. */
  357. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->cl_ip_addr)))
  358. goto error;
  359. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  360. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  361. the IP address string (which is used by other parts of NLB, such as the UI)
  362. consistent, we convert back to a string. */
  363. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  364. goto error;
  365. /* Convert the ASCII string to unicode. */
  366. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->cl_ip_addr, WLBS_MAX_CL_IP_ADDR + 1))
  367. goto error;
  368. }
  369. /* If the cluster netmask is not 0.0.0.0, then make sure the netmask is valid. */
  370. if (lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK)) {
  371. /* Check the validity of the IP address. */
  372. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->cl_net_mask)))
  373. goto error;
  374. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  375. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  376. the IP address string (which is used by other parts of NLB, such as the UI)
  377. consistent, we convert back to a string. */
  378. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  379. goto error;
  380. /* Convert the ASCII string to unicode. */
  381. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->cl_net_mask, WLBS_MAX_CL_NET_MASK + 1))
  382. goto error;
  383. }
  384. /* If the dedicated IP address is not 0.0.0.0, then make sure the IP address is valid. */
  385. if (lstrcmpi(paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR)) {
  386. /* Check the validity of the IP address. */
  387. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->ded_ip_addr)))
  388. goto error;
  389. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  390. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  391. the IP address string (which is used by other parts of NLB, such as the UI)
  392. consistent, we convert back to a string. */
  393. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  394. goto error;
  395. /* Convert the ASCII string to unicode. */
  396. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->ded_ip_addr, WLBS_MAX_DED_IP_ADDR + 1))
  397. goto error;
  398. }
  399. /* If the dedicated netmask is not 0.0.0.0, then make sure the netmask is valid. */
  400. if (lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK)) {
  401. /* Check the validity of the IP address. */
  402. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp->ded_net_mask)))
  403. goto error;
  404. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  405. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  406. the IP address string (which is used by other parts of NLB, such as the UI)
  407. consistent, we convert back to a string. */
  408. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  409. goto error;
  410. /* Convert the ASCII string to unicode. */
  411. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp->ded_net_mask, WLBS_MAX_DED_NET_MASK + 1))
  412. goto error;
  413. }
  414. /* Verify that the port rule VIP is valid,
  415. Also, convert the port rule VIPs that might be in the x.x.x or x.x or x form to x.x.x.x */
  416. idx = 0;
  417. num_rules = paramp -> i_num_rules;
  418. while (idx < num_rules)
  419. {
  420. port_rule = &paramp->i_port_rules[idx];
  421. /* Check if the port rule is valid and the vip is not "All Vip" */
  422. if (port_rule->valid && lstrcmpi(port_rule->virtual_ip_addr, CVY_DEF_ALL_VIP))
  423. {
  424. /* Get IP Address into DWORD form */
  425. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(port_rule->virtual_ip_addr)))
  426. goto error;
  427. /* Check for validity of IP Address */
  428. if ((dwIPAddr.S_un.S_un_b.s_b1 < WLBS_IP_FIELD_ZERO_LOW)
  429. || (dwIPAddr.S_un.S_un_b.s_b1 > WLBS_IP_FIELD_ZERO_HIGH)
  430. || (dwIPAddr.S_un.S_un_b.s_b2 < WLBS_FIELD_LOW)
  431. || (dwIPAddr.S_un.S_un_b.s_b2 > WLBS_FIELD_HIGH)
  432. || (dwIPAddr.S_un.S_un_b.s_b3 < WLBS_FIELD_LOW)
  433. || (dwIPAddr.S_un.S_un_b.s_b3 > WLBS_FIELD_HIGH)
  434. || (dwIPAddr.S_un.S_un_b.s_b4 < WLBS_FIELD_LOW)
  435. || (dwIPAddr.S_un.S_un_b.s_b4 > WLBS_FIELD_HIGH))
  436. goto error;
  437. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  438. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  439. the IP address string (which is used by other parts of NLB, such as the UI)
  440. consistent, we convert back to a string. */
  441. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  442. goto error;
  443. /* Convert the ASCII string to unicode. */
  444. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, port_rule->virtual_ip_addr, WLBS_MAX_CL_IP_ADDR + 1))
  445. goto error;
  446. }
  447. idx++;
  448. }
  449. /* If either the cluster IP address or the cluster netmask is not 0.0.0.0,
  450. then make sure the they are a valid IP address/netmask pair. */
  451. if (lstrcmpi(paramp->cl_ip_addr, CVY_DEF_CL_IP_ADDR) || lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK)) {
  452. /* If they have specified a cluster IP address, but no netmask, then fill it in for them. */
  453. if (!lstrcmpi(paramp->cl_net_mask, CVY_DEF_CL_NET_MASK))
  454. {
  455. ParamsGenerateSubnetMask(paramp->cl_ip_addr, paramp->cl_net_mask, ASIZECCH(paramp->cl_net_mask));
  456. }
  457. /* Check for valid cluster IP address/netmask pairs. */
  458. if (!IsValidIPAddressSubnetMaskPair(paramp->cl_ip_addr, paramp->cl_net_mask))
  459. goto error;
  460. /* Check to make sure that the cluster netmask is contiguous. */
  461. if (!IsContiguousSubnetMask(paramp->cl_net_mask))
  462. goto error;
  463. /* Check to make sure that the dedicated IP and cluster IP are not the same. */
  464. if (!wcscmp(paramp->ded_ip_addr, paramp->cl_ip_addr))
  465. goto error;
  466. }
  467. /* If either the dedicated IP address or the dedicated netmask is not 0.0.0.0,
  468. then make sure the they are a valid IP address/netmask pair. */
  469. if (lstrcmpi(paramp->ded_ip_addr, CVY_DEF_DED_IP_ADDR) || lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK)) {
  470. /* If they have specified a cluster IP address, but no netmask, then fill it in for them. */
  471. if (!lstrcmpi(paramp->ded_net_mask, CVY_DEF_DED_NET_MASK))
  472. {
  473. ParamsGenerateSubnetMask(paramp->ded_ip_addr, paramp->ded_net_mask, ASIZECCH(paramp->ded_net_mask));
  474. }
  475. /* Check for valid dedicated IP address/netmask pairs. */
  476. if (!IsValidIPAddressSubnetMaskPair(paramp->ded_ip_addr, paramp->ded_net_mask))
  477. goto error;
  478. /* Check to make sure that the dedicated netmask is contiguous. */
  479. if (!IsContiguousSubnetMask(paramp->ded_net_mask))
  480. goto error;
  481. }
  482. /* Check the mac address if the convert_mac flag is not set */
  483. if ( ! paramp -> i_convert_mac)
  484. {
  485. PWCHAR p1, p2;
  486. WCHAR mac_addr [WLBS_MAX_NETWORK_ADDR + 1];
  487. DWORD i, j;
  488. BOOL flag = TRUE;
  489. ARRAYSTRCPY (mac_addr, paramp -> cl_mac_addr);
  490. p2 = p1 = mac_addr;
  491. for (i = 0 ; i < 6 ; i++)
  492. {
  493. if (*p2 == _TEXT('\0'))
  494. {
  495. flag = FALSE;
  496. break;
  497. }
  498. j = _tcstoul (p1, &p2, 16);
  499. if ( j > 255)
  500. {
  501. flag = FALSE;
  502. break;
  503. }
  504. if ( ! (*p2 == _TEXT('-') || *p2 == _TEXT(':') || *p2 == _TEXT('\0')) )
  505. {
  506. flag = FALSE;
  507. break;
  508. }
  509. if (*p2 == _TEXT('\0') && i < 5)
  510. {
  511. flag = FALSE;
  512. break;
  513. }
  514. p1 = p2 + 1;
  515. p2 = p1;
  516. }
  517. if (!flag)
  518. {
  519. goto error;
  520. }
  521. }
  522. if (paramp->fIGMPSupport && !paramp->mcast_support)
  523. {
  524. //
  525. // IGMP can not be enabled in unicast mode
  526. //
  527. goto error;
  528. }
  529. if (paramp->mcast_support && paramp->fIGMPSupport && !paramp->fIpToMCastIp)
  530. {
  531. //
  532. // Verify that the multicast IP is a valid IP form. Ignore default value case since it isn't a valid IP.
  533. //
  534. if (lstrcmpi(paramp -> szMCastIpAddress, CVY_DEF_MCAST_IP_ADDR)) {
  535. /* Check the validity of the IP address. */
  536. if (!(dwIPAddr.S_un.S_addr = IpAddressFromAbcdWsz(paramp -> szMCastIpAddress)))
  537. goto error;
  538. /* Convert the DWORD back to a string. We do this because 11.11.3 is a valid IP
  539. address the inet_addr converts to 11.11.0.3 as a DWORD. Therefore, to keep
  540. the IP address string (which is used by other parts of NLB, such as the UI)
  541. consistent, we convert back to a string. */
  542. if (!(szIPAddr = inet_ntoa(dwIPAddr)))
  543. goto error;
  544. /* Convert the ASCII string to unicode. */
  545. if (!MultiByteToWideChar(CP_ACP, 0, szIPAddr, -1, paramp -> szMCastIpAddress, WLBS_MAX_CL_IP_ADDR + 1))
  546. goto error;
  547. }
  548. //
  549. // Multicast mode with IGMP enabled, and user specified an multicast IP address,
  550. // The multicast IP address should be in the range of (224-239).x.x.x
  551. // but NOT (224-239).0.0.x or (224-239).128.0.x.
  552. //
  553. DWORD dwMCastIp = IpAddressFromAbcdWsz(paramp->szMCastIpAddress);
  554. if ((dwMCastIp & 0xf0) != 0xe0 ||
  555. (dwMCastIp & 0x00ffff00) == 0 ||
  556. (dwMCastIp & 0x00ffff00) == 0x00008000)
  557. {
  558. goto error;
  559. }
  560. }
  561. /* Generate the MAC address. */
  562. ParamsGenerateMAC(paramp->cl_ip_addr, paramp->cl_mac_addr, ASIZECCH(paramp->cl_mac_addr), paramp->szMCastIpAddress, ASIZECCH(paramp->szMCastIpAddress), paramp->i_convert_mac,
  563. paramp->mcast_support, paramp->fIGMPSupport, paramp->fIpToMCastIp);
  564. //
  565. // We only process bda information if bda teaming is active. We can ignore these properties if it isn't. Dependencies
  566. // such as WriteRegParam will check this too to see if they should process the information.
  567. //
  568. if (paramp -> bda_teaming . active) {
  569. GUID TeamGuid;
  570. HRESULT hr;
  571. //
  572. // We don't validate the lower bound for unsigned words when the lower bound is 0. Otherwise we
  573. // get a compiler warning, promoted to an error, because such a test can't fail
  574. //
  575. // Ignore lower bound checking
  576. //
  577. CVY_CHECK_MAX (paramp -> bda_teaming . master, 1);
  578. CVY_CHECK_MAX (paramp -> bda_teaming . reverse_hash, 1);
  579. //
  580. // End Ignore lower bound checking
  581. //
  582. //
  583. // A teaming ID must be a GUID. Validate that it is, but we don't care what value. This means we ignore
  584. // the content of TeamGuid.
  585. //
  586. hr = CLSIDFromString(paramp -> bda_teaming . team_id, &TeamGuid);
  587. // If the conversion fails, bail out - the team ID must not have been a GUID
  588. if (hr != NOERROR) {
  589. goto error;
  590. }
  591. }
  592. fRet = TRUE;
  593. goto end;
  594. error:
  595. fRet = FALSE;
  596. goto end;
  597. end:
  598. return fRet;
  599. }