Source code of Windows XP (NT5)
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.

2345 lines
83 KiB

  1. /*
  2. * File: print.c
  3. * Description: This file contains the implementation of the print
  4. * utilities for the NLB KD extensions.
  5. * Author: Created by shouse, 1.4.01
  6. */
  7. #include "nlbkd.h"
  8. #include "utils.h"
  9. #include "print.h"
  10. /*
  11. * Function: PrintUsage
  12. * Description: Prints usage information for the specified context.
  13. * Author: Created by shouse, 1.5.01
  14. */
  15. void PrintUsage (ULONG dwContext) {
  16. /* Display the appropriate help. */
  17. switch (dwContext) {
  18. case USAGE_ADAPTERS:
  19. dprintf("Usage: nlbadapters [verbosity]\n");
  20. dprintf(" [verbosity]: 0 (LOW) Prints minimal detail for adapters in use (default)\n");
  21. dprintf(" 1 (MEDIUM) Prints adapter state for adapters in use\n");
  22. dprintf(" 2 (HIGH) Prints adapter state for ALL NLB adapter blocks\n");
  23. break;
  24. case USAGE_ADAPTER:
  25. dprintf("Usage: nlbadapter <pointer to adapter block> [verbosity]\n");
  26. dprintf(" [verbosity]: 0 (LOW) Prints minimal detail for the specified adapter\n");
  27. dprintf(" 1 (MEDIUM) Prints adapter state for the specified adapter (default)\n");
  28. dprintf(" 2 (HIGH) Recurses into NLB context with LOW verbosity\n");
  29. break;
  30. case USAGE_CONTEXT:
  31. dprintf("Usage: nlbctxt <pointer to context block> [verbosity]\n");
  32. dprintf(" [verbosity]: 0 (LOW) Prints fundamental NLB configuration and state (default)\n");
  33. dprintf(" 1 (MEDIUM) Prints resource state and packet statistics\n");
  34. dprintf(" 2 (HIGH) Recurses into parameters and load with LOW verbosity\n");
  35. break;
  36. case USAGE_PARAMS:
  37. dprintf("Usage: nlbparams <pointer to params block> [verbosity]\n");
  38. dprintf(" [verbosity]: 0 (LOW) Prints fundamental NLB configuration parameters (default)\n");
  39. dprintf(" 1 (MEDIUM) Prints all configured port rules\n");
  40. dprintf(" 2 (HIGH) Prints extra miscellaneous configuration\n");
  41. break;
  42. case USAGE_LOAD:
  43. dprintf("Usage: nlbload <pointer to load block> [verbosity]\n");
  44. dprintf(" [verbosity]: 0 (LOW) Prints fundamental load state and configuration\n");
  45. dprintf(" 1 (MEDIUM) Prints the state of all port rules and bins\n");
  46. dprintf(" 2 (HIGH) Prints the NLB heartbeat information\n");
  47. break;
  48. case USAGE_RESP:
  49. dprintf("Usage: nlbresp <pointer to packet> [direction]\n");
  50. dprintf(" [direction]: 0 (RECEIVE) Packet is on the receive path (default)\n");
  51. dprintf(" 1 (SEND) Packet is on the send path\n");
  52. break;
  53. case USAGE_CONNQ:
  54. dprintf("Usage: nlbconnq <pointer to queue> [max entries]\n");
  55. dprintf(" [max entries]: Maximum number of entries to print (default is ALL)\n");
  56. break;
  57. case USAGE_MAP:
  58. dprintf("Usage: nlbmap <pointer to load block> <client IP> <client port> <server IP> <server port> [protocol] [packet type]\n");
  59. dprintf(" [protocol]: TCP or UDP (default is TCP)\n");
  60. dprintf(" [packet type]: For TCP connections, one of SYN, DATA, FIN or RST (default is SYN)\n");
  61. dprintf("\n");
  62. dprintf(" IP Address can be in dotted notation or network byte order DWORDs\n");
  63. break;
  64. default:
  65. dprintf("No usage information available.\n");
  66. break;
  67. }
  68. }
  69. /*
  70. * Function: PrintAdapter
  71. * Description: Prints the contents of the MAIN_ADAPTER structure at the specified verbosity.
  72. * LOW (0) prints only the adapter address and device name.
  73. * MEDIUM (1) additionally prints the status flags (init, bound, annouce, etc.).
  74. * HIGH (2) recurses into the context structure and prints it at MEDIUM verbosity.
  75. * Author: Created by shouse, 1.5.01
  76. */
  77. void PrintAdapter (ULONG64 pAdapter, ULONG dwVerbosity) {
  78. WCHAR szString[256];
  79. ULONG dwValue;
  80. ULONG64 pAddr;
  81. /* Make sure the address is non-NULL. */
  82. if (!pAdapter) {
  83. dprintf("Error: NLB adapter block is NULL.\n");
  84. return;
  85. }
  86. dprintf("NLB Adapter Block 0x%p\n", pAdapter);
  87. /* Get the MAIN_ADAPTER_CODE from the structure to make sure that this address
  88. indeed points to a valid NLB adapter block. */
  89. GetFieldValue(pAdapter, MAIN_ADAPTER, MAIN_ADAPTER_FIELD_CODE, dwValue);
  90. if (dwValue != MAIN_ADAPTER_CODE) {
  91. dprintf(" Error: Invalid NLB adapter block. Wrong code found (0x%08x).\n", dwValue);
  92. return;
  93. }
  94. /* Retrieve the used/unused state of the adapter. */
  95. GetFieldValue(pAdapter, MAIN_ADAPTER, MAIN_ADAPTER_FIELD_USED, dwValue);
  96. if (!dwValue)
  97. dprintf(" This adapter is unused.\n");
  98. else {
  99. /* Get the pointer to and length of the device to which NLB is bound. */
  100. GetFieldValue(pAdapter, MAIN_ADAPTER, MAIN_ADAPTER_FIELD_NAME_LENGTH, dwValue);
  101. GetFieldValue(pAdapter, MAIN_ADAPTER, MAIN_ADAPTER_FIELD_NAME, pAddr);
  102. /* Retrieve the contexts of the string and store it in a buffer. */
  103. GetString(pAddr, szString, dwValue);
  104. dprintf(" Physical device name: %ls\n", szString);
  105. }
  106. /* If we're printing at low verbosity, bail out here. */
  107. if (dwVerbosity == VERBOSITY_LOW) return;
  108. /* Determine whether or not the adapter has been initialized. */
  109. GetFieldValue(pAdapter, MAIN_ADAPTER, MAIN_ADAPTER_FIELD_INITED, dwValue);
  110. dprintf(" Context state initialized: %s\n", (dwValue) ? "Yes" : "No");
  111. /* Determine whether or not NLB has been bound to the stack yet. */
  112. GetFieldValue(pAdapter, MAIN_ADAPTER, MAIN_ADAPTER_FIELD_BOUND, dwValue);
  113. dprintf(" NLB bound to adapter: %s\n", (dwValue) ? "Yes" : "No");
  114. /* Determine whether or not TCP/IP has been bound to the NLB virtual adapter or not. */
  115. GetFieldValue(pAdapter, MAIN_ADAPTER, MAIN_ADAPTER_FIELD_ANNOUNCED, dwValue);
  116. dprintf(" NLB miniport announced: %s\n", (dwValue) ? "Yes" : "No");
  117. /* Get the offset of the NLB context pointer. */
  118. if (GetFieldOffset(MAIN_ADAPTER, MAIN_ADAPTER_FIELD_CONTEXT, &dwValue))
  119. dprintf("Can't get offset of %s in %s\n", MAIN_ADAPTER_FIELD_CONTEXT, MAIN_ADAPTER);
  120. else {
  121. pAddr = pAdapter + dwValue;
  122. /* Retrieve the pointer. */
  123. pAddr = GetPointerFromAddress(pAddr);
  124. dprintf(" %sNLB context: 0x%p\n",
  125. (pAddr && (dwVerbosity == VERBOSITY_HIGH)) ? "-" : (pAddr) ? "+" : " ", pAddr);
  126. }
  127. /* If we're printing at medium verbosity, bail out here. */
  128. if (dwVerbosity == VERBOSITY_MEDIUM) return;
  129. /* Print the context information (always with LOW verbosity during recursion. */
  130. if (pAddr) {
  131. dprintf("\n");
  132. PrintContext(pAddr, VERBOSITY_LOW);
  133. }
  134. }
  135. /*
  136. * Function: PrintContext
  137. * Description: Prints the contents of the MAIN_CTXT structure at the specified verbosity.
  138. * LOW (0) prints fundamental NLB configuration and state.
  139. * MEDIUM (1) additionally prints the resource state (pools, allocations, etc).
  140. * HIGH (2) further prints other miscelaneous information.
  141. * Author: Created by shouse, 1.5.01
  142. */
  143. void PrintContext (ULONG64 pContext, ULONG dwVerbosity) {
  144. WCHAR szNICName[CVY_MAX_VIRTUAL_NIC];
  145. ULONGLONG dwwValue;
  146. IN_ADDR dwIPAddr;
  147. CHAR * szString;
  148. UCHAR szMAC[6];
  149. ULONG64 pAddr;
  150. ULONG dwValue;
  151. /* Make sure the address is non-NULL. */
  152. if (!pContext) {
  153. dprintf("Error: NLB context block is NULL.\n");
  154. return;
  155. }
  156. dprintf("NLB Context Block 0x%p\n", pContext);
  157. /* Get the MAIN_CTXT_CODE from the structure to make sure that this address
  158. indeed points to a valid NLB context block. */
  159. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CODE, dwValue);
  160. if (dwValue != MAIN_CTXT_CODE) {
  161. dprintf(" Error: Invalid NLB context block. Wrong code found (0x%08x).\n", dwValue);
  162. return;
  163. }
  164. /* Get the offset of the NLB virtual NIC name. */
  165. if (GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_VIRTUAL_NIC, &dwValue))
  166. dprintf("Can't get offset of %s in %s\n", MAIN_CTXT_FIELD_VIRTUAL_NIC, MAIN_CTXT);
  167. else {
  168. pAddr = pContext + dwValue;
  169. /* Retrieve the contexts of the string and store it in a buffer. */
  170. GetString(pAddr, szNICName, CVY_MAX_VIRTUAL_NIC);
  171. dprintf(" NLB virtual NIC name: %ls\n", szNICName);
  172. }
  173. /* Get the convoy enabled status. */
  174. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_ENABLED, dwValue);
  175. dprintf(" NLB enabled: %s ", (dwValue) ? "Yes" : "No");
  176. /* Get the draining status. */
  177. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_DRAINING, dwValue);
  178. if (dwValue) dprintf("(Draining) ");
  179. /* Get the suspended status. */
  180. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_SUSPENDED, dwValue);
  181. if (dwValue) dprintf("(Suspended) ");
  182. /* Get the stopping status. */
  183. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_STOPPING, dwValue);
  184. if (dwValue) dprintf("(Stopping) ");
  185. dprintf("\n");
  186. /* Get the adapter index. */
  187. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_ADAPTER_ID, dwValue);
  188. dprintf(" NLB adapter ID: %u\n", dwValue);
  189. dprintf("\n");
  190. /* Get the adapter medium. */
  191. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_MEDIUM, dwValue);
  192. dprintf(" Network medium: %s\n", (dwValue == NdisMedium802_3) ? "802.3" : "FDDI");
  193. /* Get the media connect status. */
  194. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_MEDIA_CONNECT, dwValue);
  195. dprintf(" Network connect status: %s\n", (dwValue) ? "Connected" : "Disconnected");
  196. /* Get the media connect status. */
  197. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_FRAME_SIZE, dwValue);
  198. dprintf(" Frame size (MTU): %u\n", dwValue);
  199. /* Get the media connect status. */
  200. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_MCAST_LIST_SIZE, dwValue);
  201. dprintf(" Multicast MAC list size: %u\n", dwValue);
  202. /* Determine dynamic MAC address support. */
  203. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_MAC_OPTIONS, dwValue);
  204. dprintf(" Dynamic MAC address support: %s\n",
  205. (dwValue & NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE) ? "Yes" : "No");
  206. dprintf("\n");
  207. dprintf(" NDIS handles\n");
  208. /* Get the NDIS bind handle. */
  209. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_BIND_HANDLE, pAddr);
  210. dprintf(" Bind handle: 0x%p\n", pAddr);
  211. /* Get the NDIS unbind handle. */
  212. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_UNBIND_HANDLE, pAddr);
  213. dprintf(" Unbind handle: 0x%p\n", pAddr);
  214. /* Get the NDIS MAC handle. */
  215. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_MAC_HANDLE, pAddr);
  216. dprintf(" MAC handle: 0x%p\n", pAddr);
  217. /* Get the NDIS protocol handle. */
  218. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_PROT_HANDLE, pAddr);
  219. dprintf(" Protocol handle: 0x%p\n", pAddr);
  220. dprintf("\n");
  221. dprintf(" Cluster IP settings\n");
  222. /* Get the cluster IP address, which is a DWORD, and convert it to a string. */
  223. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CL_IP_ADDR, dwValue);
  224. dwIPAddr.S_un.S_addr = dwValue;
  225. szString = inet_ntoa(dwIPAddr);
  226. dprintf(" IP address: %s\n", szString);
  227. /* Get the cluster net mask, which is a DWORD, and convert it to a string. */
  228. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CL_NET_MASK, dwValue);
  229. dwIPAddr.S_un.S_addr = dwValue;
  230. szString = inet_ntoa(dwIPAddr);
  231. dprintf(" Netmask: %s\n", szString);
  232. /* Get the offset of the cluster MAC address and retrieve the MAC from that address. */
  233. if (GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_CL_MAC_ADDR, &dwValue))
  234. dprintf("Can't get offset of %s in %s\n", MAIN_CTXT_FIELD_CL_MAC_ADDR, MAIN_CTXT);
  235. else {
  236. pAddr = pContext + dwValue;
  237. GetMAC(pAddr, szMAC, 6);
  238. dprintf(" MAC address: %02X-%02X-%02X-%02X-%02X-%02X\n",
  239. ((PUCHAR)(szMAC))[0], ((PUCHAR)(szMAC))[1], ((PUCHAR)(szMAC))[2],
  240. ((PUCHAR)(szMAC))[3], ((PUCHAR)(szMAC))[4], ((PUCHAR)(szMAC))[5]);
  241. }
  242. /* Get the cluster broadcast address, which is a DWORD, and convert it to a string. */
  243. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CL_BROADCAST, dwValue);
  244. dwIPAddr.S_un.S_addr = dwValue;
  245. szString = inet_ntoa(dwIPAddr);
  246. dprintf(" Broadcast address: %s\n", szString);
  247. /* Get the IGMP multicast IP address, which is a DWORD, and convert it to a string. */
  248. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_IGMP_MCAST_IP, dwValue);
  249. dwIPAddr.S_un.S_addr = dwValue;
  250. szString = inet_ntoa(dwIPAddr);
  251. dprintf(" IGMP multicast IP address: %s\n", szString);
  252. dprintf("\n");
  253. dprintf(" Dedicated IP settings\n");
  254. /* Get the dedicated IP address, which is a DWORD, and convert it to a string. */
  255. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_DED_IP_ADDR, dwValue);
  256. dwIPAddr.S_un.S_addr = dwValue;
  257. szString = inet_ntoa(dwIPAddr);
  258. dprintf(" IP address: %s\n", szString);
  259. /* Get the dedicated net mask, which is a DWORD, and convert it to a string. */
  260. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_DED_NET_MASK, dwValue);
  261. dwIPAddr.S_un.S_addr = dwValue;
  262. szString = inet_ntoa(dwIPAddr);
  263. dprintf(" Netmask: %s\n", szString);
  264. /* Get the dedicated broadcast address, which is a DWORD, and convert it to a string. */
  265. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_DED_BROADCAST, dwValue);
  266. dwIPAddr.S_un.S_addr = dwValue;
  267. szString = inet_ntoa(dwIPAddr);
  268. dprintf(" Broadcast address: %s\n", szString);
  269. /* Get the offset of the dedicated MAC address and retrieve the MAC from that address. */
  270. if (GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_DED_MAC_ADDR, &dwValue))
  271. dprintf("Can't get offset of %s in %s\n", MAIN_CTXT_FIELD_DED_MAC_ADDR, MAIN_CTXT);
  272. else {
  273. pAddr = pContext + dwValue;
  274. GetMAC(pAddr, szMAC, 6);
  275. dprintf(" MAC address: %02X-%02X-%02X-%02X-%02X-%02X\n",
  276. ((PUCHAR)(szMAC))[0], ((PUCHAR)(szMAC))[1], ((PUCHAR)(szMAC))[2],
  277. ((PUCHAR)(szMAC))[3], ((PUCHAR)(szMAC))[4], ((PUCHAR)(szMAC))[5]);
  278. }
  279. dprintf("\n");
  280. #if defined (SBH)
  281. dprintf(" Cluster MAC addresses\n");
  282. /* Get the offset of the unicast MAC address and retrieve the MAC from that address. */
  283. if (GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_UNICAST_MAC_ADDR, &dwValue))
  284. dprintf("Can't get offset of %s in %s\n", MAIN_CTXT_FIELD_UNICAST_MAC_ADDR, MAIN_CTXT);
  285. else {
  286. pAddr = pContext + dwValue;
  287. GetMAC(pAddr, szMAC, 6);
  288. dprintf(" Unicast: %02X-%02X-%02X-%02X-%02X-%02X\n",
  289. ((PUCHAR)(szMAC))[0], ((PUCHAR)(szMAC))[1], ((PUCHAR)(szMAC))[2],
  290. ((PUCHAR)(szMAC))[3], ((PUCHAR)(szMAC))[4], ((PUCHAR)(szMAC))[5]);
  291. }
  292. /* Get the offset of the multicast MAC address and retrieve the MAC from that address. */
  293. if (GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_MULTICAST_MAC_ADDR, &dwValue))
  294. dprintf("Can't get offset of %s in %s\n", MAIN_CTXT_FIELD_MULTICAST_MAC_ADDR, MAIN_CTXT);
  295. else {
  296. pAddr = pContext + dwValue;
  297. GetMAC(pAddr, szMAC, 6);
  298. dprintf(" Multicast: %02X-%02X-%02X-%02X-%02X-%02X\n",
  299. ((PUCHAR)(szMAC))[0], ((PUCHAR)(szMAC))[1], ((PUCHAR)(szMAC))[2],
  300. ((PUCHAR)(szMAC))[3], ((PUCHAR)(szMAC))[4], ((PUCHAR)(szMAC))[5]);
  301. }
  302. /* Get the offset of the IGMP MAC address and retrieve the MAC from that address. */
  303. if (GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_IGMP_MAC_ADDR, &dwValue))
  304. dprintf("Can't get offset of %s in %s\n", MAIN_CTXT_FIELD_IGMP_MAC_ADDR, MAIN_CTXT);
  305. else {
  306. pAddr = pContext + dwValue;
  307. GetMAC(pAddr, szMAC, 6);
  308. dprintf(" IGMP: %02X-%02X-%02X-%02X-%02X-%02X\n",
  309. ((PUCHAR)(szMAC))[0], ((PUCHAR)(szMAC))[1], ((PUCHAR)(szMAC))[2],
  310. ((PUCHAR)(szMAC))[3], ((PUCHAR)(szMAC))[4], ((PUCHAR)(szMAC))[5]);
  311. }
  312. dprintf("\n");
  313. #endif /* SBH */
  314. /* Get the offset of the BDA teaming information for this context. */
  315. if (GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_BDA_TEAMING, &dwValue))
  316. dprintf("Can't get offset of %s in %s\n", MAIN_CTXT_FIELD_BDA_TEAMING, MAIN_CTXT);
  317. else {
  318. pAddr = pContext + dwValue;
  319. /* Print the bi-directional affinity teaming state. */
  320. PrintBDAMember(pAddr);
  321. }
  322. dprintf("\n");
  323. /* Get the current heartbeat period. */
  324. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_PING_TIMEOUT, dwValue);
  325. dprintf(" Current heartbeat period: %u millisecond(s)\n", dwValue);
  326. /* Get the current IGMP join counter. */
  327. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_IGMP_TIMEOUT, dwValue);
  328. dprintf(" Time since last IGMP join: %.1f second(s)\n", (float)(dwValue/1000.0));
  329. /* If we're printing at low verbosity, go to the end and print the load and params pointers. */
  330. if (dwVerbosity == VERBOSITY_LOW) goto end;
  331. dprintf("\n");
  332. dprintf(" Send packet pools\n");
  333. /* Get the state of the send packet pool. */
  334. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_EXHAUSTED, dwValue);
  335. dprintf(" Pool exhausted: %s\n", (dwValue) ? "Yes" : "No");
  336. /* Get the number of send packet pools allocated. */
  337. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_SEND_POOLS_ALLOCATED, dwValue);
  338. dprintf(" Pools allocated: %u\n", dwValue);
  339. /* Get the number of send packets allocated. */
  340. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_SEND_PACKETS_ALLOCATED, dwValue);
  341. dprintf(" Packets allocated: %u\n", dwValue);
  342. /* Get the current send packet pool. */
  343. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_SEND_POOL_CURRENT, dwValue);
  344. dprintf(" Current pool: %u\n", dwValue);
  345. /* Get the number of pending send packets (outstanding). */
  346. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_SEND_OUTSTANDING, dwValue);
  347. dprintf(" Packets outstanding: %u\n", dwValue);
  348. dprintf("\n");
  349. dprintf(" Receive packet pools\n");
  350. /* Get the receive "out of resoures" counter. */
  351. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_NO_BUF, dwValue);
  352. dprintf(" Allocation failures: %u\n", dwValue);
  353. /* Get the number of receive packet pools allocated. */
  354. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_RECV_POOLS_ALLOCATED, dwValue);
  355. dprintf(" Pools allocated: %u\n", dwValue);
  356. /* Get the number of receive packets allocated. */
  357. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_RECV_PACKETS_ALLOCATED, dwValue);
  358. dprintf(" Packets allocated: %u\n", dwValue);
  359. /* Get the current receive packet pool. */
  360. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_RECV_POOL_CURRENT, dwValue);
  361. dprintf(" Current pool: %u\n", dwValue);
  362. /* Get the number of pending receive packets (outstanding). */
  363. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_RECV_OUTSTANDING, dwValue);
  364. dprintf(" Packets outstanding: %u\n", dwValue);
  365. dprintf("\n");
  366. dprintf(" Ping/IGMP packet pool (not accurate yet)\n");
  367. /* Get the receive "out of resoures" counter. */
  368. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_PING_NO_BUF, dwValue);
  369. dprintf(" Allocation failures: %u\n", dwValue);
  370. /* Get the number of ping/igmp packets allocated. */
  371. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_PING_PACKETS_ALLOCATED, dwValue);
  372. dprintf(" Packets allocated: %u\n", dwValue);
  373. /* Get the number of pending ping/igmp packets (outstanding). */
  374. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_PING_OUTSTANDING, dwValue);
  375. dprintf(" Packets outstanding: %u\n", dwValue);
  376. dprintf("\n");
  377. dprintf(" Receive buffer pools\n");
  378. /* Get the number of receive buffer pools allocated. */
  379. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_BUF_POOLS_ALLOCATED, dwValue);
  380. dprintf(" Pools allocated: %u\n", dwValue);
  381. /* Get the number of receive buffers allocated. */
  382. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_BUFS_ALLOCATED, dwValue);
  383. dprintf(" Buffers allocated: %u\n", dwValue);
  384. /* Get the number of pending receive buffers (outstanding). */
  385. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_BUFS_OUTSTANDING, dwValue);
  386. dprintf(" Buffers outstanding: %u\n", dwValue);
  387. dprintf("\n");
  388. dprintf(" NLB Main Protocol Reserved buffers\n");
  389. /* Get the address of the resp lookaside list, then use it to get the size of
  390. the list and the total number of allocations and frees. */
  391. GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_RESP, &dwValue);
  392. pAddr = pContext + dwValue;
  393. GetFieldValue(pAddr, GENERAL_LOOKASIDE, GENERAL_LOOKASIDE_FIELD_ALLOCATES, dwValue);
  394. dprintf(" Total allocations: %u\n", dwValue);
  395. GetFieldValue(pAddr, GENERAL_LOOKASIDE, GENERAL_LOOKASIDE_FIELD_FREES, dwValue);
  396. dprintf(" Total frees: %u\n", dwValue);
  397. GetFieldValue(pAddr, GENERAL_LOOKASIDE, GENERAL_LOOKASIDE_FIELD_SIZE, dwValue);
  398. dprintf(" Current lookaside list size: %u\n", dwValue);
  399. dprintf("\n");
  400. dprintf(" Sent Received\n");
  401. dprintf(" Statistics ---------- ----------\n");
  402. /* Get the number of successful sends. */
  403. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_XMIT_OK, dwValue);
  404. dprintf(" Successful: %10u", dwValue);
  405. /* Get the number of successful receives. */
  406. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_OK, dwValue);
  407. dprintf(" %10u\n", dwValue);
  408. /* Get the number of unsuccessful sends. */
  409. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_XMIT_ERROR, dwValue);
  410. dprintf(" Unsuccessful: %10u", dwValue);
  411. /* Get the number of unsuccessful receives. */
  412. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_ERROR, dwValue);
  413. dprintf(" %10u\n", dwValue);
  414. /* Get the number of directed frames transmitted. */
  415. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_XMIT_FRAMES_DIR, dwValue);
  416. dprintf(" Directed packets: %10u", dwValue);
  417. /* Get the number of directed frames received. */
  418. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_FRAMES_DIR, dwValue);
  419. dprintf(" %10u\n", dwValue);
  420. /* Get the number of directed bytes transmitted. */
  421. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_XMIT_BYTES_DIR, dwwValue);
  422. dprintf(" Directed bytes: %10u", dwwValue);
  423. /* Get the number of directed bytes received. */
  424. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_BYTES_DIR, dwwValue);
  425. dprintf(" %10u\n", dwValue);
  426. /* Get the number of multicast frames transmitted. */
  427. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_XMIT_FRAMES_MCAST, dwValue);
  428. dprintf(" Multicast packets: %10u", dwValue);
  429. /* Get the number of multicast frames received. */
  430. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_FRAMES_MCAST, dwValue);
  431. dprintf(" %10u\n", dwValue);
  432. /* Get the number of multicast bytes transmitted. */
  433. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_XMIT_BYTES_MCAST, dwwValue);
  434. dprintf(" Multicast bytes: %10u", dwwValue);
  435. /* Get the number of multicast bytes received. */
  436. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_BYTES_MCAST, dwwValue);
  437. dprintf(" %10u\n", dwValue);
  438. /* Get the number of broadcast frames transmitted. */
  439. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_XMIT_FRAMES_BCAST, dwValue);
  440. dprintf(" Broadcast packets: %10u", dwValue);
  441. /* Get the number of broadcast frames received. */
  442. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_FRAMES_BCAST, dwValue);
  443. dprintf(" %10u\n", dwValue);
  444. /* Get the number of broadcast bytes transmitted. */
  445. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_XMIT_BYTES_BCAST, dwwValue);
  446. dprintf(" Broadcast bytes: %10u", dwwValue);
  447. /* Get the number of broadcast bytes received. */
  448. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CNTR_RECV_BYTES_BCAST, dwwValue);
  449. dprintf(" %10u\n", dwValue);
  450. end:
  451. dprintf("\n");
  452. /* Get the pointer to the NLB load. */
  453. GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_LOAD, &dwValue);
  454. pAddr = pContext + dwValue;
  455. dprintf(" %sNLB load: 0x%p\n",
  456. (pAddr && (dwVerbosity == VERBOSITY_HIGH)) ? "-" : (pAddr) ? "+" : " ", pAddr);
  457. /* Print the load information if verbosity is high. */
  458. if (pAddr && (dwVerbosity == VERBOSITY_HIGH)) {
  459. dprintf("\n");
  460. PrintLoad(pAddr, VERBOSITY_LOW);
  461. dprintf("\n");
  462. }
  463. /* Get the pointer to the NLB parameters. */
  464. GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_PARAMS, &dwValue);
  465. pAddr = pContext + dwValue;
  466. dprintf(" %sNLB parameters: 0x%p ",
  467. (pAddr && (dwVerbosity == VERBOSITY_HIGH)) ? "-" : (pAddr) ? "+" : " ", pAddr);
  468. /* Get the validity of the NLB parameter block. */
  469. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_PARAMS_VALID, dwValue);
  470. dprintf("(%s)\n", (dwValue) ? "Valid" : "Invalid");
  471. /* Print the parameter information if verbosity is high. */
  472. if (pAddr && (dwVerbosity == VERBOSITY_HIGH)) {
  473. dprintf("\n");
  474. PrintParams(pAddr, VERBOSITY_LOW);
  475. }
  476. }
  477. /*
  478. * Function: PrintParams
  479. * Description: Prints the contents of the CVY_PARAMS structure at the specified verbosity.
  480. * LOW (0) prints fundamental configuration parameters.
  481. * MEDIUM (1) prints all configured port rules.
  482. * HIGH (2) prints other miscellaneous configuration.
  483. * Author: Created by shouse, 1.21.01
  484. */
  485. void PrintParams (ULONG64 pParams, ULONG dwVerbosity) {
  486. WCHAR szString[256];
  487. ULONG64 pAddr;
  488. ULONG dwValue;
  489. /* Make sure the address is non-NULL. */
  490. if (!pParams) {
  491. dprintf("Error: NLB parameter block is NULL.\n");
  492. return;
  493. }
  494. /* Get the parameter version number. */
  495. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_VERSION, dwValue);
  496. dprintf("NLB Parameters Block 0x%p (Version %d)\n", pParams, dwValue);
  497. /* Get the host priority. */
  498. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_HOST_PRIORITY, dwValue);
  499. dprintf(" Host priority: %u\n", dwValue);
  500. /* Get the initial cluster state flag. */
  501. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_INITIAL_STATE, dwValue);
  502. dprintf(" Initial cluster state: %s\n", (dwValue) ? "Active" : "Inactive");
  503. dprintf("\n");
  504. /* Get the multicast support flag. */
  505. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_MULTICAST_SUPPORT, dwValue);
  506. dprintf(" Multicast support enabled: %s\n", (dwValue) ? "Yes" : "No");
  507. /* Get the IGMP support flag. */
  508. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_IGMP_SUPPORT, dwValue);
  509. dprintf(" IGMP multicast support enabled: %s\n", (dwValue) ? "Yes" : "No");
  510. dprintf("\n");
  511. dprintf(" Remote control settings\n");
  512. /* Get the remote control support flag. */
  513. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_REMOTE_CONTROL_ENABLED, dwValue);
  514. dprintf(" Enabled: %s\n", (dwValue) ? "Yes" : "No");
  515. /* Get the remote control port. */
  516. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_REMOTE_CONTROL_PORT, dwValue);
  517. dprintf(" Port number: %u\n", dwValue);
  518. /* Get the host priority. */
  519. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_REMOTE_CONTROL_PASSWD, dwValue);
  520. dprintf(" Password: 0x%08x\n", dwValue);
  521. dprintf("\n");
  522. dprintf(" Cluster IP settings\n");
  523. /* Get the offset of the cluster IP address and retrieve the string from that address. */
  524. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_CL_IP_ADDR, &dwValue))
  525. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_CL_IP_ADDR, CVY_PARAMS);
  526. else {
  527. pAddr = pParams + dwValue;
  528. /* Retrieve the contexts of the string and store it in a buffer. */
  529. GetString(pAddr, szString, CVY_MAX_CL_IP_ADDR + 1);
  530. dprintf(" IP address: %ls\n", szString);
  531. }
  532. /* Get the offset of the cluster netmask and retrieve the string from that address. */
  533. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_CL_NET_MASK, &dwValue))
  534. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_CL_NET_MASK, CVY_PARAMS);
  535. else {
  536. pAddr = pParams + dwValue;
  537. /* Retrieve the contexts of the string and store it in a buffer. */
  538. GetString(pAddr, szString, CVY_MAX_CL_NET_MASK + 1);
  539. dprintf(" Netmask: %ls\n", szString);
  540. }
  541. /* Get the offset of the cluster MAC address and retrieve the MAC from that address. */
  542. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_CL_MAC_ADDR, &dwValue))
  543. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_CL_MAC_ADDR, CVY_PARAMS);
  544. else {
  545. pAddr = pParams + dwValue;
  546. /* Retrieve the contexts of the string and store it in a buffer. */
  547. GetString(pAddr, szString, CVY_MAX_NETWORK_ADDR + 1);
  548. dprintf(" MAC address: %ls\n", szString);
  549. }
  550. /* Get the offset of the cluster IGMP multicast address and retrieve the string from that address. */
  551. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_CL_IGMP_ADDR, &dwValue))
  552. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_CL_IGMP_ADDR, CVY_PARAMS);
  553. else {
  554. pAddr = pParams + dwValue;
  555. /* Retrieve the contexts of the string and store it in a buffer. */
  556. GetString(pAddr, szString, CVY_MAX_CL_IGMP_ADDR + 1);
  557. dprintf(" IGMP multicast IP address: %ls\n", szString);
  558. }
  559. /* Get the offset of the cluster name and retrieve the string from that address. */
  560. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_CL_NAME, &dwValue))
  561. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_CL_NAME, CVY_PARAMS);
  562. else {
  563. pAddr = pParams + dwValue;
  564. /* Retrieve the contexts of the string and store it in a buffer. */
  565. GetString(pAddr, szString, CVY_MAX_DOMAIN_NAME + 1);
  566. dprintf(" Domain name: %ls\n", szString);
  567. }
  568. dprintf("\n");
  569. dprintf(" Dedicated IP settings\n");
  570. /* Get the offset of the dedicated IP address and retrieve the string from that address. */
  571. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_DED_IP_ADDR, &dwValue))
  572. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_DED_IP_ADDR, CVY_PARAMS);
  573. else {
  574. pAddr = pParams + dwValue;
  575. /* Retrieve the contexts of the string and store it in a buffer. */
  576. GetString(pAddr, szString, CVY_MAX_DED_IP_ADDR + 1);
  577. dprintf(" IP address: %ls\n", szString);
  578. }
  579. /* Get the offset of the dedicated netmask and retrieve the string from that address. */
  580. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_DED_NET_MASK, &dwValue))
  581. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_DED_NET_MASK, CVY_PARAMS);
  582. else {
  583. pAddr = pParams + dwValue;
  584. /* Retrieve the contexts of the string and store it in a buffer. */
  585. GetString(pAddr, szString, CVY_MAX_DED_NET_MASK + 1);
  586. dprintf(" Netmask: %ls\n", szString);
  587. }
  588. dprintf("\n");
  589. /* Get the offset of the BDA teaming parameters structure. */
  590. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_BDA_TEAMING, &dwValue))
  591. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_BDA_TEAMING, CVY_PARAMS);
  592. else {
  593. ULONG64 pBDA = pParams + dwValue;
  594. /* Find out whether or not teaming is active on this adapter. */
  595. GetFieldValue(pBDA, CVY_BDA, CVY_BDA_FIELD_ACTIVE, dwValue);
  596. dprintf(" Bi-directional affinity teaming: %s\n", (dwValue) ? "Active" : "Inactive");
  597. /* Get the offset of the team ID and retrieve the string from that address. */
  598. if (GetFieldOffset(CVY_BDA, CVY_BDA_FIELD_TEAM_ID, &dwValue))
  599. dprintf("Can't get offset of %s in %s\n", CVY_BDA_FIELD_TEAM_ID, CVY_BDA);
  600. else {
  601. pAddr = pBDA + dwValue;
  602. /* Retrieve the contexts of the string and store it in a buffer. */
  603. GetString(pAddr, szString, CVY_MAX_BDA_TEAM_ID + 1);
  604. dprintf(" Team ID: %ls\n", szString);
  605. }
  606. /* Get the master flag. */
  607. GetFieldValue(pBDA, CVY_BDA, CVY_BDA_FIELD_MASTER, dwValue);
  608. dprintf(" Master: %s\n", (dwValue) ? "Yes" : "No");
  609. /* Get the reverse hashing flag. */
  610. GetFieldValue(pBDA, CVY_BDA, CVY_BDA_FIELD_REVERSE_HASH, dwValue);
  611. dprintf(" Reverse hashing: %s\n", (dwValue) ? "Yes" : "No");
  612. }
  613. /* If we're printing at low verbosity, bail out here. */
  614. if (dwVerbosity == VERBOSITY_LOW) return;
  615. dprintf("\n");
  616. /* Get the offset of the port rules and pass it to PrintPortRules. */
  617. if (GetFieldOffset(CVY_PARAMS, CVY_PARAMS_FIELD_PORT_RULES, &dwValue))
  618. dprintf("Can't get offset of %s in %s\n", CVY_PARAMS_FIELD_PORT_RULES, CVY_PARAMS);
  619. else {
  620. pAddr = pParams + dwValue;
  621. /* Get the number of port rules. */
  622. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_NUM_RULES, dwValue);
  623. PrintPortRules(dwValue, pAddr);
  624. }
  625. /* If we're printing at medium verbosity, bail out here. */
  626. if (dwVerbosity == VERBOSITY_MEDIUM) return;
  627. dprintf("\n");
  628. /* Get the heartbeat period. */
  629. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_ALIVE_PERIOD, dwValue);
  630. dprintf(" Heartbeat period: %u millisecond(s)\n", dwValue);
  631. /* Get the heartbeat loss tolerance. */
  632. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_ALIVE_TOLERANCE, dwValue);
  633. dprintf(" Heartbeat loss tolerance: %u\n", dwValue);
  634. dprintf("\n");
  635. /* Get the number of remote control actions to allocate. */
  636. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_NUM_ACTIONS, dwValue);
  637. dprintf(" Number of actions to allocate: %u\n", dwValue);
  638. /* Get the number of packets to allocate. */
  639. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_NUM_PACKETS, dwValue);
  640. dprintf(" Number of packets to allocate: %u\n", dwValue);
  641. /* Get the number of heartbeats to allocate. */
  642. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_NUM_PINGS, dwValue);
  643. dprintf(" Number of heartbeats to allocate: %u\n", dwValue);
  644. /* Get the number of descriptors per allocation. */
  645. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_NUM_DESCR, dwValue);
  646. dprintf(" Descriptors per allocation: %u\n", dwValue);
  647. /* Get the maximum number of descriptor allocations. */
  648. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_MAX_DESCR, dwValue);
  649. dprintf(" Maximum Descriptors allocations: %u\n", dwValue);
  650. dprintf("\n");
  651. /* Get the NetBT support flag. */
  652. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_NBT_SUPPORT, dwValue);
  653. dprintf(" NetBT support enabled: %s\n", (dwValue) ? "Yes" : "No");
  654. /* Get the multicast spoof flag. */
  655. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_MCAST_SPOOF, dwValue);
  656. dprintf(" Multicast spoofing enabled: %s\n", (dwValue) ? "Yes" : "No");
  657. /* Get the netmon passthru flag. */
  658. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_NETMON_PING, dwValue);
  659. dprintf(" Netmon heartbeat passthru enabled: %s\n", (dwValue) ? "Yes" : "No");
  660. /* Get the mask source MAC flag. */
  661. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_MASK_SRC_MAC, dwValue);
  662. dprintf(" Mask source MAC enabled: %s\n", (dwValue) ? "Yes" : "No");
  663. /* Get the convert MAC flag. */
  664. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_CONVERT_MAC, dwValue);
  665. dprintf(" IP to MAC conversion enabled: %s\n", (dwValue) ? "Yes" : "No");
  666. dprintf("\n");
  667. /* Get the IP change delay value. */
  668. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_IP_CHANGE_DELAY, dwValue);
  669. dprintf(" IP change delay: %u millisecond(s)\n", dwValue);
  670. /* Get the dirty descriptor cleanup delay value. */
  671. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_CLEANUP_DELAY, dwValue);
  672. dprintf(" Dirty connection cleanup delay: %u millisecond(s)\n", dwValue);
  673. }
  674. /*
  675. * Function: PrintPortRules
  676. * Description: Prints the NLB port rules.
  677. * Author: Created by shouse, 1.21.01
  678. */
  679. void PrintPortRules (ULONG dwNumRules, ULONG64 pRules) {
  680. ULONG dwRuleSize;
  681. ULONG dwIndex;
  682. ULONG64 pAddr;
  683. /* Make sure the address is non-NULL. */
  684. if (!pRules) {
  685. dprintf("Error: NLB port rule block is NULL.\n");
  686. return;
  687. }
  688. dprintf(" Configured port rules (%u)\n", dwNumRules);
  689. /* If no port rules are present, print a notification. */
  690. if (!dwNumRules) {
  691. dprintf(" There are no port rules configured on this cluster.\n");
  692. return;
  693. }
  694. /* Print the column headers. */
  695. dprintf(" Virtual IP Start End Protocol Mode Priority Load Weight Affinity\n");
  696. dprintf(" --------------- ----- ----- -------- -------- -------- ----------- --------\n");
  697. /* Find out the size of a CVY_RULE structure. */
  698. dwRuleSize = GetTypeSize(CVY_RULE);
  699. /* Loop through all port rules and print the configuration. Note: The print statements
  700. are full of seemingly non-sensicle format strings, but trust me, they're right. */
  701. for (dwIndex = 0; dwIndex < dwNumRules; dwIndex++) {
  702. IN_ADDR dwIPAddr;
  703. CHAR * szString;
  704. ULONG dwValue;
  705. USHORT wValue;
  706. /* Get the VIP. Convert from a DWORD to a string. */
  707. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_VIP, dwValue);
  708. if (dwValue != CVY_ALL_VIP) {
  709. dwIPAddr.S_un.S_addr = dwValue;
  710. szString = inet_ntoa(dwIPAddr);
  711. dprintf(" %-15s", szString);
  712. } else
  713. dprintf(" %-15s", "ALL VIPs");
  714. /* Get the start port. */
  715. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_START_PORT, dwValue);
  716. dprintf(" %5u", dwValue);
  717. /* Get the end port. */
  718. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_END_PORT, dwValue);
  719. dprintf(" %5u", dwValue);
  720. /* Figure out the protocol. */
  721. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_PROTOCOL, dwValue);
  722. switch (dwValue) {
  723. case CVY_TCP:
  724. dprintf(" %s ", "TCP");
  725. break;
  726. case CVY_UDP:
  727. dprintf(" %s ", "UDP");
  728. break;
  729. case CVY_TCP_UDP:
  730. dprintf(" %s ", "Both");
  731. break;
  732. default:
  733. dprintf(" %s", "Unknown");
  734. break;
  735. }
  736. /* Find the rule mode. */
  737. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_MODE, dwValue);
  738. switch (dwValue) {
  739. case CVY_SINGLE:
  740. /* Print mode and priority. */
  741. dprintf(" %s ", "Single");
  742. /* Get the handling priority. */
  743. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_PRIORITY, dwValue);
  744. dprintf(" %2u ", dwValue);
  745. break;
  746. case CVY_MULTI:
  747. /* Print mode, weight and affinity. */
  748. dprintf(" %s", "Multiple");
  749. dprintf(" %8s", "");
  750. /* Get the equal load flag. */
  751. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_EQUAL_LOAD, wValue);
  752. if (wValue) {
  753. dprintf(" %5s ", "Equal");
  754. } else {
  755. /* If distribution is unequal, get the load weight. */
  756. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_LOAD_WEIGHT, dwValue);
  757. dprintf(" %3u ", dwValue);
  758. }
  759. /* Get the affinity for this rule. */
  760. GetFieldValue(pRules, CVY_RULE, CVY_RULE_FIELD_AFFINITY, wValue);
  761. switch (wValue) {
  762. case CVY_AFFINITY_NONE:
  763. dprintf(" %s", "None");
  764. break;
  765. case CVY_AFFINITY_SINGLE:
  766. dprintf(" %s", "Single");
  767. break;
  768. case CVY_AFFINITY_CLASSC:
  769. dprintf(" %s", "Class C");
  770. break;
  771. default:
  772. dprintf(" %s", "Unknown");
  773. break;
  774. }
  775. break;
  776. case CVY_NEVER:
  777. /* Print the mode. */
  778. dprintf(" %s", "Disabled");
  779. break;
  780. default:
  781. break;
  782. }
  783. dprintf("\n");
  784. /* Advance the pointer to the next index in the array of structures. */
  785. pRules += dwRuleSize;
  786. }
  787. }
  788. /*
  789. * Function: PrintLoad
  790. * Description: Prints the contents of the CVY_LOAD structure at the specified verbosity.
  791. * LOW (0)
  792. * MEDIUM (1)
  793. * HIGH (2)
  794. * Author: Created by shouse, 1.21.01
  795. */
  796. void PrintLoad (ULONG64 pLoad, ULONG dwVerbosity) {
  797. WCHAR szString[256];
  798. ULONG dwMissedPings[CVY_MAX_HOSTS];
  799. BOOL dwDirtyBins[CVY_MAX_BINS];
  800. ULONG64 pAddr;
  801. ULONG dwValue;
  802. ULONG dwHostID;
  803. BOOL bValue;
  804. /* Make sure the address is non-NULL. */
  805. if (!pLoad) {
  806. dprintf("Error: NLB load block is NULL.\n");
  807. return;
  808. }
  809. dprintf("NLB Load Block 0x%p\n", pLoad);
  810. /* Get the LOAD_CTXT_CODE from the structure to make sure that this address
  811. indeed points to a valid NLB load block. */
  812. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_CODE, dwValue);
  813. if (dwValue != LOAD_CTXT_CODE) {
  814. dprintf(" Error: Invalid NLB load block. Wrong code found (0x%08x).\n", dwValue);
  815. return;
  816. }
  817. /* Get my host ID. */
  818. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_HOST_ID, dwHostID);
  819. /* Determine whether or not the load context has been initialized. */
  820. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_REF_COUNT, dwValue);
  821. dprintf(" Reference count: %u\n", dwValue);
  822. /* Determine whether or not the load context has been initialized. */
  823. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_INIT, bValue);
  824. dprintf(" Load initialized: %s\n", (bValue) ? "Yes" : "No");
  825. /* Determine whether or not the load context is active. */
  826. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_ACTIVE, bValue);
  827. dprintf(" Load active: %s\n", (bValue) ? "Yes" : "No");
  828. /* Get the number of total packets handled since last convergence. */
  829. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_PACKET_COUNT, dwValue);
  830. dprintf(" Packets handled since convergence: %u\n", dwValue);
  831. /* Get the number of currently active connections. */
  832. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_CONNECTIONS, dwValue);
  833. dprintf(" Current active connections: %u\n", dwValue);
  834. dprintf("\n");
  835. /* Find out the level of consistency from incoming heartbeats. */
  836. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_CONSISTENT, bValue);
  837. dprintf(" Consistent heartbeats detected: %s\n", (bValue) ? "Yes" : "No");
  838. /* Have we seen duplicate host IDs? */
  839. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_DUP_HOST_ID, bValue);
  840. dprintf(" Duplicate host IDs: %s\n", (bValue) ? "Yes" : "No");
  841. /* Have we seen duplicate handling priorities? */
  842. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_DUP_PRIORITY, bValue);
  843. dprintf(" Duplicate handling priorities: %s\n", (bValue) ? "Yes" : "No");
  844. /* Have we seen inconsistent BDA teaming configuration? */
  845. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_BAD_TEAM_CONFIG, bValue);
  846. dprintf(" Inconsistent BDA teaming: %s\n", (bValue) ? "Yes" : "No");
  847. /* Have we seen a different number of port rules? */
  848. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_BAD_NUM_RULES, bValue);
  849. dprintf(" Different number of port rules: %s\n", (bValue) ? "Yes" : "No");
  850. /* Is the new host map bad? */
  851. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_BAD_NEW_MAP, bValue);
  852. dprintf(" Invalid new host map: %s\n", (bValue) ? "Yes" : "No");
  853. /* Do the maps overlap? */
  854. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_OVERLAPPING_MAP, bValue);
  855. dprintf(" Overlapping maps: %s\n", (bValue) ? "Yes" : "No");
  856. /* Was there an error in updating bins? */
  857. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_RECEIVING_BINS, bValue);
  858. dprintf(" Received bins already owned: %s\n", (bValue) ? "Yes" : "No");
  859. /* Were there orphaned bins after an update? */
  860. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_ORPHANED_BINS, bValue);
  861. dprintf(" Orphaned bins: %s\n", (bValue) ? "Yes" : "No");
  862. dprintf("\n");
  863. /* Get the current host map. */
  864. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_HOST_MAP, dwValue);
  865. dprintf(" Current host map: 0x%08x ", dwValue);
  866. /* If there are hosts in the map, print them. */
  867. if (dwValue) {
  868. dprintf("(");
  869. PrintHostList(dwValue);
  870. dprintf(")");
  871. }
  872. dprintf("\n");
  873. /* Get the current map of pinged hosts. */
  874. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_PING_MAP, dwValue);
  875. dprintf(" Ping'd host map: 0x%08x ", dwValue);
  876. /* If there are hosts in the map, print them. */
  877. if (dwValue) {
  878. dprintf("(");
  879. PrintHostList(dwValue);
  880. dprintf(")");
  881. }
  882. dprintf("\n");
  883. /* Get the map from the last convergence. */
  884. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_LAST_MAP, dwValue);
  885. dprintf(" Host map after last convergence: 0x%08x ", dwValue);
  886. /* If there are hosts in the map, print them. */
  887. if (dwValue) {
  888. dprintf("(");
  889. PrintHostList(dwValue);
  890. dprintf(")");
  891. }
  892. dprintf("\n");
  893. dprintf("\n");
  894. /* Get the stable host map. */
  895. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_STABLE_MAP, dwValue);
  896. dprintf(" Stable host map: 0x%08x ", dwValue);
  897. /* If there are hosts in the map, print them. */
  898. if (dwValue) {
  899. dprintf("(");
  900. PrintHostList(dwValue);
  901. dprintf(")");
  902. }
  903. dprintf("\n");
  904. /* Get the minimum number of timeouts with stable condition. */
  905. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_MIN_STABLE, dwValue);
  906. dprintf(" Stable timeouts necessary: %u\n", dwValue);
  907. /* Get the number of local stable timeouts. */
  908. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_LOCAL_STABLE, dwValue);
  909. dprintf(" Local stable timeouts: %u\n", dwValue);
  910. /* Get the number of global stable timeouts. */
  911. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_ALL_STABLE, dwValue);
  912. dprintf(" Global stable timeouts: %u\n", dwValue);
  913. dprintf("\n");
  914. /* Get the default timeout period. */
  915. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_DEFAULT_TIMEOUT, dwValue);
  916. dprintf(" Default timeout interval: %u millisecond(s)\n", dwValue);
  917. /* Get the current timeout period. */
  918. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_CURRENT_TIMEOUT, dwValue);
  919. dprintf(" Current timeout interval: %u millisecond(s)\n", dwValue);
  920. /* Get the ping miss tolerance. */
  921. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_PING_TOLERANCE, dwValue);
  922. dprintf(" Missed ping tolerance: %u\n", dwValue);
  923. /* Get the missed ping array. */
  924. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_PING_MISSED, dwMissedPings);
  925. dprintf(" Missed pings: ");
  926. PrintMissedPings(dwMissedPings);
  927. dprintf("\n");
  928. /* Are we waiting for a cleanup? */
  929. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_CLEANUP_WAITING, bValue);
  930. dprintf(" Cleanup waiting: %s\n", (bValue) ? "Yes" : "No");
  931. /* Get the cleanup timeout. */
  932. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_CLEANUP_TIMEOUT, dwValue);
  933. dprintf(" Cleanup timeout: %.1f second(s)\n", (float)(dwValue/1000.0));
  934. /* Get the current cleanup wait time. */
  935. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_CLEANUP_CURRENT, dwValue);
  936. dprintf(" Current cleanup wait time: %.1f second(s)\n", (float)(dwValue/1000.0));
  937. dprintf("\n");
  938. /* Get the number of descriptors per allocation. */
  939. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_DESCRIPTORS_PER_ALLOC, dwValue);
  940. dprintf(" Descriptors per allocation: %u\n", dwValue);
  941. /* Get the maximum number of allocations allowed. */
  942. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_MAX_DESCRIPTOR_ALLOCS, dwValue);
  943. dprintf(" Maximum descriptor allocations: %u\n", dwValue);
  944. /* Get the number of allocations thusfar. */
  945. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_NUM_DESCRIPTOR_ALLOCS, dwValue);
  946. dprintf(" Number of descriptor allocations: %u\n", dwValue);
  947. /* Get the inhibited allocations flag. */
  948. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_INHIBITED_ALLOC, bValue);
  949. dprintf(" Allocations inhibited: %s\n", (bValue) ? "Yes" : "No");
  950. /* Get the failed allocations flag. */
  951. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_FAILED_ALLOC, bValue);
  952. dprintf(" Allocations failed: %s\n", (bValue) ? "Yes" : "No");
  953. /* If wer're printing at low verbosity, bail out here. */
  954. if (dwVerbosity == VERBOSITY_LOW) return;
  955. dprintf("\n");
  956. /* Get the dirty bin array. */
  957. GetFieldValue(pLoad, LOAD_CTXT, LOAD_CTXT_FIELD_DIRTY_BINS, dwDirtyBins);
  958. dprintf(" Dirty bins: ");
  959. /* Print the bins which have dirty connections. */
  960. PrintDirtyBins(dwDirtyBins);
  961. dprintf("\n");
  962. /* Get the offset of the port rule state structures and use PrintPortRuleState to print them. */
  963. if (GetFieldOffset(LOAD_CTXT, LOAD_CTXT_FIELD_PORT_RULE_STATE, &dwValue))
  964. dprintf("Can't get offset of %s in %s\n", LOAD_CTXT_FIELD_PORT_RULE_STATE, LOAD_CTXT);
  965. else {
  966. ULONG dwPortRuleStateSize;
  967. ULONG dwNumRules;
  968. ULONG dwIndex;
  969. ULONG dwTemp;
  970. /* Get the offset of the params pointer. */
  971. if (GetFieldOffset(LOAD_CTXT, LOAD_CTXT_FIELD_PARAMS, &dwTemp))
  972. dprintf("Can't get offset of %s in %s\n", LOAD_CTXT_FIELD_PARAMS, LOAD_CTXT);
  973. else {
  974. pAddr = pLoad + dwTemp;
  975. /* Retrieve the pointer. */
  976. pAddr = GetPointerFromAddress(pAddr);
  977. /* Get the number of port rules from the params block. */
  978. GetFieldValue(pAddr, CVY_PARAMS, CVY_PARAMS_FIELD_NUM_RULES, dwNumRules);
  979. /* Set the address of the port rule state array. */
  980. pAddr = pLoad + dwValue;
  981. /* Find out the size of a BIN_STATE structure. */
  982. dwPortRuleStateSize = GetTypeSize(BIN_STATE);
  983. /* NOTE: its "less than or equal" as opposed to "less than" because we need to include
  984. the DEFAULT port rule, which is always at index "num rules" (i.e. the last rule). */
  985. for (dwIndex = 0; dwIndex <= dwNumRules; dwIndex++) {
  986. /* Print the state information for the port rule. */
  987. PrintPortRuleState(pAddr, dwHostID, (dwIndex == dwNumRules) ? TRUE : FALSE);
  988. if (dwIndex < dwNumRules) dprintf("\n");
  989. /* Advance the pointer to the next port rule. */
  990. pAddr += dwPortRuleStateSize;
  991. }
  992. }
  993. }
  994. /* If wer're printing at medium verbosity, bail out here. */
  995. if (dwVerbosity == VERBOSITY_MEDIUM) return;
  996. dprintf("\n");
  997. dprintf(" Heartbeat message\n");
  998. /* Get the offset of the heartbeat structure and use PrintHeartbeat to print it. */
  999. if (GetFieldOffset(LOAD_CTXT, LOAD_CTXT_FIELD_PING, &dwValue))
  1000. dprintf("Can't get offset of %s in %s\n", LOAD_CTXT_FIELD_PING, LOAD_CTXT);
  1001. else {
  1002. pAddr = pLoad + dwValue;
  1003. /* Print the NLB heartbeat contents. */
  1004. PrintHeartbeat(pAddr);
  1005. }
  1006. }
  1007. /*
  1008. * Function: PrintResp
  1009. * Description: Prints the NLB private data associated with the given packet.
  1010. * Author: Created by shouse, 1.31.01
  1011. */
  1012. void PrintResp (ULONG64 pPacket, ULONG dwDirection) {
  1013. ULONG64 pPacketStack;
  1014. ULONG bStackLeft;
  1015. ULONG64 pProtReserved = 0;
  1016. ULONG64 pIMReserved = 0;
  1017. ULONG64 pMPReserved = 0;
  1018. ULONG64 pResp;
  1019. ULONG64 pAddr;
  1020. ULONG dwValue;
  1021. USHORT wValue;
  1022. /* Make sure the address is non-NULL. */
  1023. if (!pPacket) {
  1024. dprintf("Error: Packet is NULL.\n");
  1025. return;
  1026. }
  1027. /* Print a warning concerning the importance of knowing whether its a send or receive. */
  1028. dprintf("Assuming packet 0x%p is on the %s packet path. If this is\n", pPacket,
  1029. (dwDirection == DIRECTION_RECEIVE) ? "RECEIVE" : "SEND");
  1030. dprintf(" incorrect, the information displayed below MAY be incorrect.\n");
  1031. dprintf("\n");
  1032. /* Get the current NDIS packet stack. */
  1033. pPacketStack = PrintCurrentPacketStack(pPacket, &bStackLeft);
  1034. dprintf("\n");
  1035. if (pPacketStack) {
  1036. /* Get the offset of the IMReserved field in the packet stack. */
  1037. if (GetFieldOffset(NDIS_PACKET_STACK, NDIS_PACKET_STACK_FIELD_IMRESERVED, &dwValue))
  1038. dprintf("Can't get offset of %s in %s\n", NDIS_PACKET_STACK_FIELD_IMRESERVED, NDIS_PACKET_STACK);
  1039. else {
  1040. pAddr = pPacketStack + dwValue;
  1041. /* Get the resp pointer from the IMReserved field. */
  1042. pIMReserved = GetPointerFromAddress(pAddr);
  1043. }
  1044. }
  1045. /* Get the offset of the MiniportReserved field in the packet. */
  1046. if (GetFieldOffset(NDIS_PACKET, NDIS_PACKET_FIELD_MPRESERVED, &dwValue))
  1047. dprintf("Can't get offset of %s in %s\n", NDIS_PACKET_FIELD_MPRESERVED, NDIS_PACKET);
  1048. else {
  1049. pAddr = pPacket + dwValue;
  1050. /* Get the resp pointer from the MPReserved field. */
  1051. pMPReserved = GetPointerFromAddress(pAddr);
  1052. }
  1053. /* Get the offset of the ProtocolReserved field in the packet. */
  1054. if (GetFieldOffset(NDIS_PACKET, NDIS_PACKET_FIELD_PROTRESERVED, &dwValue))
  1055. dprintf("Can't get offset of %s in %s\n", NDIS_PACKET_FIELD_PROTRESERVED, NDIS_PACKET);
  1056. else {
  1057. pProtReserved = pPacket + dwValue;
  1058. }
  1059. /* Mimic #define MAIN_RESP_FIELD(pkt, left, ps, rsp, send) (from wlbs\driver\main.h). */
  1060. if (pPacketStack) {
  1061. if (pIMReserved)
  1062. pResp = pIMReserved;
  1063. else if (dwDirection == DIRECTION_SEND)
  1064. pResp = pProtReserved;
  1065. else if (pMPReserved)
  1066. pResp = pMPReserved;
  1067. else
  1068. pResp = pProtReserved;
  1069. } else {
  1070. if (dwDirection == DIRECTION_SEND)
  1071. pResp = pProtReserved;
  1072. else if (pMPReserved)
  1073. pResp = pMPReserved;
  1074. else
  1075. pResp = pProtReserved;
  1076. }
  1077. dprintf("NLB Main Protocol Reserved Block 0x%p\n");
  1078. /* Get the offset of the miscellaneous pointer. */
  1079. if (GetFieldOffset(MAIN_PROTOCOL_RESERVED, MAIN_PROTOCOL_RESERVED_FIELD_MISCP, &dwValue))
  1080. dprintf("Can't get offset of %s in %s\n", MAIN_PROTOCOL_RESERVED_FIELD_MISCP, MAIN_PROTOCOL_RESERVED);
  1081. else {
  1082. pAddr = pResp + dwValue;
  1083. /* Retrieve the pointer. */
  1084. pAddr = GetPointerFromAddress(pAddr);
  1085. dprintf(" Miscellaneous pointer: 0x%p\n", pAddr);
  1086. }
  1087. /* Retrieve the packet type from the NLB private data. */
  1088. GetFieldValue(pResp, MAIN_PROTOCOL_RESERVED, MAIN_PROTOCOL_RESERVED_FIELD_TYPE, wValue);
  1089. switch (wValue) {
  1090. case MAIN_PACKET_TYPE_NONE:
  1091. dprintf(" Packet type: %u (None)\n", wValue);
  1092. break;
  1093. case MAIN_PACKET_TYPE_PING:
  1094. dprintf(" Packet type: %u (Heartbeat)\n", wValue);
  1095. break;
  1096. case MAIN_PACKET_TYPE_INDICATE:
  1097. dprintf(" Packet type: %u (Indicate)\n", wValue);
  1098. break;
  1099. case MAIN_PACKET_TYPE_PASS:
  1100. dprintf(" Packet type: %u (Passthrough)\n", wValue);
  1101. break;
  1102. case MAIN_PACKET_TYPE_CTRL:
  1103. dprintf(" Packet type: %u (Remote Control)\n", wValue);
  1104. break;
  1105. case MAIN_PACKET_TYPE_TRANSFER:
  1106. dprintf(" Packet type: %u (Transfer)\n", wValue);
  1107. break;
  1108. case MAIN_PACKET_TYPE_IGMP:
  1109. dprintf(" Packet type: %u (IGMP)\n", wValue);
  1110. break;
  1111. default:
  1112. dprintf(" Packet type: %u (Invalid)\n", wValue);
  1113. break;
  1114. }
  1115. /* Retrieve the group from the NLB private data. */
  1116. GetFieldValue(pResp, MAIN_PROTOCOL_RESERVED, MAIN_PROTOCOL_RESERVED_FIELD_GROUP, wValue);
  1117. switch (wValue) {
  1118. case MAIN_FRAME_UNKNOWN:
  1119. dprintf(" Packet type: %u (Unknown)\n", wValue);
  1120. break;
  1121. case MAIN_FRAME_DIRECTED:
  1122. dprintf(" Packet type: %u (Directed)\n", wValue);
  1123. break;
  1124. case MAIN_FRAME_MULTICAST:
  1125. dprintf(" Packet type: %u (Multicast)\n", wValue);
  1126. break;
  1127. case MAIN_FRAME_BROADCAST:
  1128. dprintf(" Packet type: %u (Broadcast)\n", wValue);
  1129. break;
  1130. default:
  1131. dprintf(" Packet type: %u (Invalid)\n", wValue);
  1132. break;
  1133. }
  1134. /* Retrieve the data field from the NLB private data. */
  1135. GetFieldValue(pResp, MAIN_PROTOCOL_RESERVED, MAIN_PROTOCOL_RESERVED_FIELD_DATA, dwValue);
  1136. dprintf(" Data: %u\n", dwValue);
  1137. /* Retrieve the length field from the NLB private data. */
  1138. GetFieldValue(pResp, MAIN_PROTOCOL_RESERVED, MAIN_PROTOCOL_RESERVED_FIELD_LENGTH, dwValue);
  1139. dprintf(" Length: %u\n", dwValue);
  1140. }
  1141. /*
  1142. * Function: PrintCurrentPacketStack
  1143. * Description: Retrieves the current packet stack for the specified packet. Note: this
  1144. * is heavily dependent on the current NDIS packet stacking mechanics - any
  1145. * changes to NDIS packet stacking could easily (will) break this. This
  1146. * entire function mimics NdisIMGetCurrentPacketStack().
  1147. * Author: Created by shouse, 1.31.01
  1148. */
  1149. ULONG64 PrintCurrentPacketStack (ULONG64 pPacket, ULONG * bStackLeft) {
  1150. ULONG64 pNumPacketStacks;
  1151. ULONG64 pPacketWrapper;
  1152. ULONG64 pPacketStack;
  1153. ULONG dwNumPacketStacks;
  1154. ULONG dwStackIndexSize;
  1155. ULONG dwPacketStackSize;
  1156. ULONG dwCurrentIndex;
  1157. /* Make sure the address is non-NULL. */
  1158. if (!pPacket) {
  1159. dprintf("Error: Packet is NULL.\n");
  1160. *bStackLeft = 0;
  1161. return 0;
  1162. }
  1163. /* Get the address of the global variable containing the number of packet stacks. */
  1164. pNumPacketStacks = GetExpression(NDIS_PACKET_STACK_SIZE);
  1165. if (!pNumPacketStacks) {
  1166. ErrorCheckSymbols(NDIS_PACKET_STACK_SIZE);
  1167. *bStackLeft = 0;
  1168. return 0;
  1169. }
  1170. /* Get the number of packet stacks from the address. */
  1171. dwNumPacketStacks = GetUlongFromAddress(pNumPacketStacks);
  1172. /* Find out the size of a STACK_INDEX structure. */
  1173. dwStackIndexSize = GetTypeSize(STACK_INDEX);
  1174. /* Find out the size of a NDIS_PACKET_STACK structure. */
  1175. dwPacketStackSize = GetTypeSize(NDIS_PACKET_STACK);
  1176. /* This is the calculation we're doing (from ndis\sys\wrapper.h):
  1177. #define SIZE_PACKET_STACKS (sizeof(STACK_INDEX) + (sizeof(NDIS_PACKET_STACK) * ndisPacketStackSize)) */
  1178. pPacketStack = pPacket - (dwStackIndexSize + (dwPacketStackSize * dwNumPacketStacks));
  1179. /* The wrapper is the packet address minus the size of the stack index.
  1180. See ndis\sys\wrapper.h. We need this to get the current stack index. */
  1181. pPacketWrapper = pPacket - dwStackIndexSize;
  1182. dprintf("NDIS Packet Stack: 0x%p\n", pPacketStack);
  1183. /* Retrieve the current stack index. */
  1184. GetFieldValue(pPacketWrapper, NDIS_PACKET_WRAPPER, NDIS_PACKET_WRAPPER_FIELD_STACK_INDEX, dwCurrentIndex);
  1185. dprintf(" Current stack index: %d\n", dwCurrentIndex);
  1186. if (dwCurrentIndex < dwNumPacketStacks) {
  1187. /* If the current index is less than the number of stacks, then point the stack to
  1188. the right address and determine whether or not there is stack room left. */
  1189. pPacketStack += dwCurrentIndex * dwPacketStackSize;
  1190. *bStackLeft = (dwNumPacketStacks - dwCurrentIndex - 1) > 0;
  1191. } else {
  1192. /* If not, then we're out of stack space. */
  1193. pPacketStack = 0;
  1194. *bStackLeft = 0;
  1195. }
  1196. dprintf(" Current packet stack: 0x%p\n", pPacketStack);
  1197. dprintf(" Stack remaining: %s\n", (*bStackLeft) ? "Yes" : "No");
  1198. return pPacketStack;
  1199. }
  1200. /*
  1201. * Function: PrintHostList
  1202. * Description: Prints a list of hosts in a host map.
  1203. * Author: Created by shouse, 2.1.01
  1204. */
  1205. void PrintHostList (ULONG dwHostMap) {
  1206. BOOL bFirst = TRUE;
  1207. ULONG dwHostNum = 1;
  1208. /* As long as there are hosts still in the map, print them. */
  1209. while (dwHostMap) {
  1210. /* If the least significant bit is set, print the host number. */
  1211. if (dwHostMap & 0x00000001) {
  1212. /* If this is the first host printed, just print the number. */
  1213. if (bFirst) {
  1214. dprintf("%u", dwHostNum);
  1215. bFirst = FALSE;
  1216. } else
  1217. /* Otherwise, we need to print a comma first. */
  1218. dprintf(", %u", dwHostNum);
  1219. }
  1220. /* Increment the host number and shift the map to the right one bit. */
  1221. dwHostNum++;
  1222. dwHostMap >>= 1;
  1223. }
  1224. }
  1225. /*
  1226. * Function: PrintMissedPings
  1227. * Description: Prints a list hosts from which we are missing pings.
  1228. * Author: Created by shouse, 2.1.01
  1229. */
  1230. void PrintMissedPings (ULONG dwMissedPings[]) {
  1231. BOOL bMissing = FALSE;
  1232. ULONG dwIndex;
  1233. /* Loop through the entire array of missed pings. */
  1234. for (dwIndex = 0; dwIndex < CVY_MAX_HOSTS; dwIndex++) {
  1235. /* If we're missing pings from this host, print the number missed and
  1236. the host priority, which is the index (host ID) plus one. */
  1237. if (dwMissedPings[dwIndex]) {
  1238. dprintf("\n Missing %u pings from Host %u", dwMissedPings[dwIndex], dwIndex + 1);
  1239. /* Not the fact that we found at least one host with missing pings. */
  1240. bMissing = TRUE;
  1241. }
  1242. }
  1243. /* If we're missing no pings, print "None". */
  1244. if (!bMissing) dprintf("None");
  1245. dprintf("\n");
  1246. }
  1247. /*
  1248. * Function: PrintDirtyBins
  1249. * Description: Prints a list of bins with dirty connections.
  1250. * Author: Created by shouse, 2.1.01
  1251. */
  1252. void PrintDirtyBins (BOOL dwDirtyBins[]) {
  1253. BOOL bFirst = TRUE;
  1254. ULONG dwIndex;
  1255. /* Loop through the entire array of dirty bins. */
  1256. for (dwIndex = 0; dwIndex < CVY_MAX_BINS; dwIndex++) {
  1257. if (dwDirtyBins[dwIndex]) {
  1258. /* If this is the first bin printed, just print the number. */
  1259. if (bFirst) {
  1260. dprintf("%u", dwIndex);
  1261. bFirst = FALSE;
  1262. } else
  1263. /* Otherwise, we need to print a comma first. */
  1264. dprintf(", %u", dwIndex);
  1265. }
  1266. }
  1267. /* If there are no dirty bins, print "None". */
  1268. if (bFirst) dprintf("None");
  1269. dprintf("\n");
  1270. }
  1271. /*
  1272. * Function: PrintHeartbeat
  1273. * Description: Prints the contents of the NLB heartbeat structure.
  1274. * Author: Created by shouse, 2.1.01
  1275. */
  1276. void PrintHeartbeat (ULONG64 pHeartbeat) {
  1277. ULONG dwValue;
  1278. USHORT wValue;
  1279. ULONG dwIndex;
  1280. ULONG dwRuleCode[CVY_MAX_RULES];
  1281. ULONGLONG ddwCurrentMap[CVY_MAX_RULES];
  1282. ULONGLONG ddwNewMap[CVY_MAX_RULES];
  1283. ULONGLONG ddwIdleMap[CVY_MAX_RULES];
  1284. ULONGLONG ddwReadyBins[CVY_MAX_RULES];
  1285. ULONG dwLoadAmount[CVY_MAX_RULES];
  1286. /* Make sure the address is non-NULL. */
  1287. if (!pHeartbeat) {
  1288. dprintf("Error: Heartbeat is NULL.\n");
  1289. return;
  1290. }
  1291. /* Get the default host ID. */
  1292. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_DEFAULT_HOST_ID, wValue);
  1293. dprintf(" DEFAULT host ID: %u (%u)\n", wValue, wValue + 1);
  1294. /* Get my host ID. */
  1295. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_HOST_ID, wValue);
  1296. dprintf(" My host ID: %u (%u)\n", wValue, wValue + 1);
  1297. /* Get my host code. */
  1298. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_HOST_CODE, dwValue);
  1299. dprintf(" Unique host code: 0x%08x\n", dwValue);
  1300. /* Get the host state. */
  1301. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_STATE, wValue);
  1302. dprintf(" Host state: ");
  1303. switch (wValue) {
  1304. case HST_CVG:
  1305. dprintf("Converging\n");
  1306. break;
  1307. case HST_STABLE:
  1308. dprintf("Stable\n");
  1309. break;
  1310. case HST_NORMAL:
  1311. dprintf("Normal\n");
  1312. break;
  1313. default:
  1314. dprintf("Unknown\n");
  1315. break;
  1316. }
  1317. /* Get the teaming configuration code. */
  1318. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_TEAMING_CODE, dwValue);
  1319. dprintf(" BDA teaming configuration: 0x%08x\n", dwValue);
  1320. /* Get the packet count. */
  1321. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_PACKET_COUNT, dwValue);
  1322. dprintf(" Packets handled: %u\n", dwValue);
  1323. /* Get the number of port rules. */
  1324. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_NUM_RULES, wValue);
  1325. dprintf(" Number of port rules: %u\n", wValue);
  1326. /* Get the rule codes. */
  1327. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_RULE_CODE, dwRuleCode);
  1328. /* Get the current bin map. */
  1329. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_CURRENT_MAP, ddwCurrentMap);
  1330. /* Get the new bin map. */
  1331. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_NEW_MAP, ddwNewMap);
  1332. /* Get the idle bin map. */
  1333. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_IDLE_MAP, ddwIdleMap);
  1334. /* Get the ready bins map. */
  1335. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_READY_BINS, ddwReadyBins);
  1336. /* Get the load amount for each rule. */
  1337. GetFieldValue(pHeartbeat, PING_MSG, PING_MSG_FIELD_LOAD_AMOUNT, dwLoadAmount);
  1338. /* Loop through all port rules and spit out some information. */
  1339. for (dwIndex = 0; dwIndex < wValue; dwIndex++) {
  1340. /* Decode the rule. See CVY_RULE_CODE_SET() in net\inc\wlbsparams.h. */
  1341. ULONG dwStartPort = dwRuleCode[dwIndex] & 0x00000fff;
  1342. ULONG dwEndPort = (dwRuleCode[dwIndex] & 0x00fff000) >> 12;
  1343. ULONG dwProtocol = (dwRuleCode[dwIndex] & 0x0f000000) >> 24;
  1344. ULONG dwMode = (dwRuleCode[dwIndex] & 0x30000000) >> 28;
  1345. ULONG dwAffinity = (dwRuleCode[dwIndex] & 0xc0000000) >> 30;
  1346. dprintf(" Port rule %u\n", dwIndex + 1);
  1347. /* Print out the bin maps and load weight. */
  1348. dprintf(" Rule code: 0x%08x ", dwRuleCode[dwIndex]);
  1349. /* If this is the last port rule, then its the default port rule. */
  1350. if (dwIndex == (wValue - 1))
  1351. dprintf("(DEFAULT port rule)\n");
  1352. else {
  1353. #if 0 /* Because rule codes are overlapped logical ORs, we can't necessarily get back the
  1354. information that was put in, so we won't spit it out until we can guarantee that. */
  1355. /* Print out the port range - keep in mind that 16 bit port ranges are
  1356. encoded in 12 bit numbers, so this may not be 100% accurate. */
  1357. dprintf("(%u - %u, ", dwStartPort, dwEndPort);
  1358. /* Print the protocol. */
  1359. switch (dwProtocol) {
  1360. case CVY_TCP:
  1361. dprintf("TCP, ");
  1362. break;
  1363. case CVY_UDP:
  1364. dprintf("UDP, ");
  1365. break;
  1366. case CVY_TCP_UDP:
  1367. dprintf("TCP/UDP, ");
  1368. break;
  1369. default:
  1370. dprintf("Unknown protocol, ");
  1371. break;
  1372. }
  1373. /* Print the filtering mode. */
  1374. switch (dwMode) {
  1375. case CVY_SINGLE:
  1376. dprintf("Single host)\n");
  1377. break;
  1378. case CVY_MULTI:
  1379. dprintf("Multiple host, ");
  1380. /* If this rule uses multiple host, then we also print the affinity. */
  1381. switch (dwAffinity) {
  1382. case CVY_AFFINITY_NONE:
  1383. dprintf("No affinity)\n");
  1384. break;
  1385. case CVY_AFFINITY_SINGLE:
  1386. dprintf("Single affinity)\n");
  1387. break;
  1388. case CVY_AFFINITY_CLASSC:
  1389. dprintf("Class C affinity)\n");
  1390. break;
  1391. default:
  1392. dprintf("Unknown affinity)\n");
  1393. break;
  1394. }
  1395. break;
  1396. case CVY_NEVER:
  1397. dprintf("Disabled)\n");
  1398. break;
  1399. default:
  1400. dprintf("Unknown filtering mode)\n");
  1401. break;
  1402. }
  1403. #else
  1404. dprintf("\n");
  1405. #endif
  1406. /* Print the load weight. */
  1407. dprintf(" Load weight: %u\n", dwLoadAmount[dwIndex]);
  1408. }
  1409. /* Print the bin maps for all rules, default or not. */
  1410. dprintf(" Current map: 0x%015I64x\n", ddwCurrentMap[dwIndex]);
  1411. dprintf(" New map: 0x%015I64x\n", ddwNewMap[dwIndex]);
  1412. dprintf(" Idle map: 0x%015I64x\n", ddwIdleMap[dwIndex]);
  1413. dprintf(" Ready bins: 0x%015I64x\n", ddwReadyBins[dwIndex]);
  1414. }
  1415. }
  1416. /*
  1417. * Function: PrintPortRuleState
  1418. * Description: Prints the state information for the port rule.
  1419. * Author: Created by shouse, 2.5.01
  1420. */
  1421. void PrintPortRuleState (ULONG64 pPortRule, ULONG dwHostID, BOOL bDefault) {
  1422. ULONG dwValue;
  1423. ULONG dwMode;
  1424. USHORT wValue;
  1425. BOOL bValue;
  1426. ULONGLONG ddwValue;
  1427. /* Make sure the address is non-NULL. */
  1428. if (!pPortRule) {
  1429. dprintf("Error: Port rule is NULL.\n");
  1430. return;
  1431. }
  1432. /* Get the BIN_STATE_CODE from the structure to make sure that this address
  1433. indeed points to a valid NLB port rule state block. */
  1434. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_CODE, dwValue);
  1435. if (dwValue != BIN_STATE_CODE) {
  1436. dprintf(" Error: Invalid NLB port rule state block. Wrong code found (0x%08x).\n", dwValue);
  1437. return;
  1438. }
  1439. /* Get the index of the rule - the "rule number". */
  1440. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_INDEX, dwValue);
  1441. dprintf(" Port rule %u\n", dwValue + 1);
  1442. /* Is the port rule state initialized? */
  1443. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_INITIALIZED, bValue);
  1444. dprintf(" State initialized: %s\n", (bValue) ? "Yes" : "No");
  1445. /* Are the codes compatible? */
  1446. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_COMPATIBLE, bValue);
  1447. dprintf(" Compatibility detected: %s\n", (bValue) ? "Yes" : "No");
  1448. /* Is the port rule state initialized? */
  1449. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_EQUAL, bValue);
  1450. dprintf(" Equal load balancing: %s\n", (bValue) ? "Yes" : "No");
  1451. /* Get the filtering mode for this port rule. */
  1452. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_MODE, dwMode);
  1453. dprintf(" Filtering mode: ");
  1454. /* If this is the DEFAULT port rule, then jump to the bottom. */
  1455. if (bDefault) {
  1456. dprintf("DEFAULT\n");
  1457. goto end;
  1458. }
  1459. switch (dwMode) {
  1460. case CVY_SINGLE:
  1461. dprintf("Single host\n");
  1462. break;
  1463. case CVY_MULTI:
  1464. dprintf("Multiple host\n");
  1465. break;
  1466. case CVY_NEVER:
  1467. dprintf("Disabled\n");
  1468. break;
  1469. default:
  1470. dprintf("Unknown\n");
  1471. break;
  1472. }
  1473. if (dwMode == CVY_MULTI) {
  1474. /* Get the affinity for this port rule. */
  1475. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_AFFINITY, wValue);
  1476. dprintf(" Affinity: ");
  1477. switch (wValue) {
  1478. case CVY_AFFINITY_NONE:
  1479. dprintf("None\n");
  1480. break;
  1481. case CVY_AFFINITY_SINGLE:
  1482. dprintf("Single\n");
  1483. break;
  1484. case CVY_AFFINITY_CLASSC:
  1485. dprintf("Class C\n");
  1486. break;
  1487. default:
  1488. dprintf("Unknown\n");
  1489. break;
  1490. }
  1491. }
  1492. /* Get the protocol(s) for this port rule. */
  1493. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_PROTOCOL, dwValue);
  1494. dprintf(" Protocol(s): ");
  1495. /* Print the protocol. */
  1496. switch (dwValue) {
  1497. case CVY_TCP:
  1498. dprintf("TCP\n");
  1499. break;
  1500. case CVY_UDP:
  1501. dprintf("UDP\n");
  1502. break;
  1503. case CVY_TCP_UDP:
  1504. dprintf("TCP/UDP\n");
  1505. break;
  1506. default:
  1507. dprintf("Unknown\n");
  1508. break;
  1509. }
  1510. /* In multiple host filtering, print the load information. For single host
  1511. filtering, print the host priority information. */
  1512. if (dwMode == CVY_MULTI) {
  1513. ULONG dwCurrentLoad[CVY_MAX_HOSTS];
  1514. /* Get the original load for this rule on this host. */
  1515. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_ORIGINAL_LOAD, dwValue);
  1516. dprintf(" Configured load weight: %u\n", dwValue);
  1517. /* Get the original load for this rule on this host. */
  1518. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_CURRENT_LOAD, dwCurrentLoad);
  1519. dprintf(" Current load weight: %u/", dwCurrentLoad[dwHostID]);
  1520. /* Get the total load for this rule on all hosts. */
  1521. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_TOTAL_LOAD, dwValue);
  1522. dprintf("%u\n", dwValue);
  1523. } else if (dwMode == CVY_SINGLE) {
  1524. /* Get the host priority. */
  1525. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_ORIGINAL_LOAD, dwValue);
  1526. dprintf(" Host priority: %u\n", dwValue);
  1527. }
  1528. end:
  1529. /* Get the total number of active connections. */
  1530. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_TOTAL_CONNECTIONS, dwValue);
  1531. dprintf(" Total active connections: %u\n", dwValue);
  1532. /* Get the current map. */
  1533. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_CURRENT_MAP, ddwValue);
  1534. dprintf(" Current map: 0x%015I64x\n", ddwValue);
  1535. /* Get the all idle map. */
  1536. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_ALL_IDLE_MAP, ddwValue);
  1537. dprintf(" All idle map: 0x%015I64x\n", ddwValue);
  1538. /* Get the idle bins map. */
  1539. GetFieldValue(pPortRule, BIN_STATE, BIN_STATE_FIELD_IDLE_BINS, ddwValue);
  1540. dprintf(" My idle map: 0x%015I64x\n", ddwValue);
  1541. }
  1542. /*
  1543. * Function: PrintBDAMember
  1544. * Description: Prints the BDA teaming configuration and state of a member.
  1545. * Author: Created by shouse, 4.8.01
  1546. */
  1547. void PrintBDAMember (ULONG64 pMember) {
  1548. ULONG64 pAddr;
  1549. ULONG dwValue;
  1550. /* Make sure the address is non-NULL. */
  1551. if (!pMember) {
  1552. dprintf("Error: Member is NULL.\n");
  1553. return;
  1554. }
  1555. /* Find out whether or not teaming is active on this adapter. */
  1556. GetFieldValue(pMember, BDA_MEMBER, BDA_MEMBER_FIELD_ACTIVE, dwValue);
  1557. dprintf(" Bi-directional affinity teaming: %s\n", (dwValue) ? "Active" : "Inactive");
  1558. /* Get the team-assigned member ID. */
  1559. GetFieldValue(pMember, BDA_MEMBER, BDA_MEMBER_FIELD_MEMBER_ID, dwValue);
  1560. if (dwValue == CVY_BDA_INVALID_MEMBER_ID)
  1561. dprintf(" Member ID: %s\n", "Invalid");
  1562. else
  1563. dprintf(" Member ID: %u\n", dwValue);
  1564. /* Get the master status flag. */
  1565. GetFieldValue(pMember, BDA_MEMBER, BDA_MEMBER_FIELD_MASTER, dwValue);
  1566. dprintf(" Master: %s\n", (dwValue) ? "Yes" : "No");
  1567. /* Get the reverse hashing flag. */
  1568. GetFieldValue(pMember, BDA_MEMBER, BDA_MEMBER_FIELD_REVERSE_HASH, dwValue);
  1569. dprintf(" Reverse hashing: %s\n", (dwValue) ? "Yes" : "No");
  1570. /* Get the pointer to the BDA team. */
  1571. GetFieldValue(pMember, BDA_MEMBER, BDA_MEMBER_FIELD_TEAM, pAddr);
  1572. dprintf(" %sBDA team: 0x%p\n", (pAddr) ? "-" : "+", pAddr);
  1573. /* If this adapter is part of a team, print out the team configuration and state. */
  1574. if (pAddr) {
  1575. dprintf("\n");
  1576. PrintBDATeam(pAddr);
  1577. }
  1578. }
  1579. /*
  1580. * Function: PrintBDAMember
  1581. * Description: Prints the BDA teaming configuration and state of a member.
  1582. * Author: Created by shouse, 4.8.01
  1583. */
  1584. void PrintBDATeam (ULONG64 pTeam) {
  1585. WCHAR szString[256];
  1586. ULONG64 pAddr;
  1587. ULONG dwValue;
  1588. /* Make sure the address is non-NULL. */
  1589. if (!pTeam) {
  1590. dprintf("Error: Team is NULL.\n");
  1591. return;
  1592. }
  1593. dprintf(" BDA Team 0x%p\n", pTeam);
  1594. /* Find out whether or not the team is active. */
  1595. GetFieldValue(pTeam, BDA_TEAM, BDA_TEAM_FIELD_ACTIVE, dwValue);
  1596. dprintf(" Active: %s\n", (dwValue) ? "Yes" : "No");
  1597. /* Get the offset of the team ID and retrieve the string from that address. */
  1598. if (GetFieldOffset(BDA_TEAM, BDA_TEAM_FIELD_TEAM_ID, &dwValue))
  1599. dprintf("Can't get offset of %s in %s\n", BDA_TEAM_FIELD_TEAM_ID, BDA_TEAM);
  1600. else {
  1601. pAddr = pTeam + dwValue;
  1602. /* Retrieve the contexts of the string and store it in a buffer. */
  1603. GetString(pAddr, szString, CVY_MAX_BDA_TEAM_ID + 1);
  1604. dprintf(" Team ID: %ls\n", szString);
  1605. }
  1606. /* Get the current membership count. */
  1607. GetFieldValue(pTeam, BDA_TEAM, BDA_TEAM_FIELD_MEMBERSHIP_COUNT, dwValue);
  1608. dprintf(" Number of members: %u\n", dwValue);
  1609. /* Get the current membership list. */
  1610. GetFieldValue(pTeam, BDA_TEAM, BDA_TEAM_FIELD_MEMBERSHIP_FINGERPRINT, dwValue);
  1611. dprintf(" Membership fingerprint: 0x%08x\n", dwValue);
  1612. /* Get the current membership map. */
  1613. GetFieldValue(pTeam, BDA_TEAM, BDA_TEAM_FIELD_MEMBERSHIP_MAP, dwValue);
  1614. dprintf(" Members: 0x%08x ", dwValue);
  1615. /* If there are members in the map, print them. */
  1616. if (dwValue) {
  1617. dprintf("(");
  1618. PrintBDAMemberList(dwValue);
  1619. dprintf(")");
  1620. }
  1621. dprintf("\n");
  1622. /* Get the current consistency map. */
  1623. GetFieldValue(pTeam, BDA_TEAM, BDA_TEAM_FIELD_CONSISTENCY_MAP, dwValue);
  1624. dprintf(" Consistent members: 0x%08x ", dwValue);
  1625. /* If there are members in the map, print them. */
  1626. if (dwValue) {
  1627. dprintf("(");
  1628. PrintBDAMemberList(dwValue);
  1629. dprintf(")");
  1630. }
  1631. dprintf("\n");
  1632. /* Get the offset of the load module pointer. */
  1633. if (GetFieldOffset(BDA_TEAM, BDA_TEAM_FIELD_LOAD, &dwValue))
  1634. dprintf("Can't get offset of %s in %s\n", BDA_TEAM_FIELD_LOAD, BDA_TEAM);
  1635. else {
  1636. pAddr = pTeam + dwValue;
  1637. /* Retrieve the pointer. */
  1638. pAddr = GetPointerFromAddress(pAddr);
  1639. dprintf(" Load: 0x%p\n", pAddr);
  1640. }
  1641. /* Get the offset of the load lock pointer. */
  1642. if (GetFieldOffset(BDA_TEAM, BDA_TEAM_FIELD_LOAD_LOCK, &dwValue))
  1643. dprintf("Can't get offset of %s in %s\n", BDA_TEAM_FIELD_LOAD_LOCK, BDA_TEAM);
  1644. else {
  1645. pAddr = pTeam + dwValue;
  1646. /* Retrieve the pointer. */
  1647. pAddr = GetPointerFromAddress(pAddr);
  1648. dprintf(" Load lock: 0x%p\n", pAddr);
  1649. }
  1650. /* Get the offset of the previous pointer. */
  1651. if (GetFieldOffset(BDA_TEAM, BDA_TEAM_FIELD_PREV, &dwValue))
  1652. dprintf("Can't get offset of %s in %s\n", BDA_TEAM_FIELD_PREV, BDA_TEAM);
  1653. else {
  1654. pAddr = pTeam + dwValue;
  1655. /* Retrieve the pointer. */
  1656. pAddr = GetPointerFromAddress(pAddr);
  1657. dprintf(" Previous BDA Team: 0x%p\n", pAddr);
  1658. }
  1659. /* Get the offset of the next pointer. */
  1660. if (GetFieldOffset(BDA_TEAM, BDA_TEAM_FIELD_NEXT, &dwValue))
  1661. dprintf("Can't get offset of %s in %s\n", BDA_TEAM_FIELD_NEXT, BDA_TEAM);
  1662. else {
  1663. pAddr = pTeam + dwValue;
  1664. /* Retrieve the pointer. */
  1665. pAddr = GetPointerFromAddress(pAddr);
  1666. dprintf(" Next BDA Team: 0x%p\n", pAddr);
  1667. }
  1668. }
  1669. /*
  1670. * Function: PrintBDAMemberList
  1671. * Description: Prints a list of members in a BDA membership or consistency map.
  1672. * Author: Created by shouse, 4.8.01
  1673. */
  1674. void PrintBDAMemberList (ULONG dwMemberMap) {
  1675. BOOL bFirst = TRUE;
  1676. ULONG dwMemberNum = 0;
  1677. /* As long as there are hosts still in the map, print them. */
  1678. while (dwMemberMap) {
  1679. /* If the least significant bit is set, print the host number. */
  1680. if (dwMemberMap & 0x00000001) {
  1681. /* If this is the first host printed, just print the number. */
  1682. if (bFirst) {
  1683. dprintf("%u", dwMemberNum);
  1684. bFirst = FALSE;
  1685. } else
  1686. /* Otherwise, we need to print a comma first. */
  1687. dprintf(", %u", dwMemberNum);
  1688. }
  1689. /* Increment the host number and shift the map to the right one bit. */
  1690. dwMemberNum++;
  1691. dwMemberMap >>= 1;
  1692. }
  1693. }
  1694. /*
  1695. * Function: PrintQueue
  1696. * Description: Prints MaxEntries entries in a connection descriptor queue.
  1697. * Author: Created by shouse, 4.15.01
  1698. */
  1699. void PrintQueue (ULONG64 pQueue, ULONG dwMaxEntries) {
  1700. }
  1701. /*
  1702. * Function: PrintMap
  1703. * Description: Searches the given load module to determine who should accept this packet. If
  1704. * state for this packet already exists, it is printed.
  1705. * Author: Created by shouse, 4.15.01
  1706. */
  1707. void PrintMap (ULONG64 pLoad, ULONG dwClientIPAddress, ULONG dwClientPort, ULONG dwServerIPAddress, ULONG dwServerPort, BOOLEAN bIsTCP, TCP_PACKET_TYPE ePktType) {
  1708. WCHAR szString[256];
  1709. ULONG64 pAddr;
  1710. ULONG dwValue;
  1711. /* Make sure the load address is non-NULL. */
  1712. if (!pLoad) {
  1713. dprintf("Error: Load is NULL.\n");
  1714. return;
  1715. }
  1716. dprintf("Looking for connection tuple (0x%08x, %u, 0x%08x, %u, %s", dwClientIPAddress, dwClientPort, dwServerIPAddress, dwServerPort, (bIsTCP) ? "TCP" : "UDP");
  1717. if (bIsTCP)
  1718. dprintf(" %s)\n", TCPPacketTypeToString(ePktType));
  1719. else
  1720. dprintf(")\n");
  1721. dprintf("Map returned: %u\n", Map(dwClientIPAddress, dwServerIPAddress));
  1722. }