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.

1293 lines
43 KiB

  1. /*
  2. * File: nlbkd.c
  3. * Description: This file contains the implementation of the NLB KD
  4. * debugging extensions. Use '!load nlbkd.dll' to load
  5. * the extensions and '!nlbkd.help' to see the supported
  6. * extensions.
  7. * Author: Created by shouse, 1.4.01
  8. */
  9. #include "nlbkd.h"
  10. #include "utils.h"
  11. #include "print.h"
  12. #include "packet.h"
  13. #include "load.h"
  14. WINDBG_EXTENSION_APIS ExtensionApis;
  15. EXT_API_VERSION ApiVersion = { 1, 0, EXT_API_VERSION_NUMBER64, 0 };
  16. #define NL 1
  17. #define NONL 0
  18. USHORT SavedMajorVersion;
  19. USHORT SavedMinorVersion;
  20. BOOL ChkTarget;
  21. /*
  22. * Function: WinDbgExtensionDllInit
  23. * Description: Initializes the KD extension DLL.
  24. * Author: Created by shouse, 1.4.01 - copied largely from ndiskd.dll
  25. */
  26. VOID WinDbgExtensionDllInit (PWINDBG_EXTENSION_APIS64 lpExtensionApis, USHORT MajorVersion, USHORT MinorVersion) {
  27. ExtensionApis = *lpExtensionApis;
  28. SavedMajorVersion = MajorVersion;
  29. SavedMinorVersion = MinorVersion;
  30. ChkTarget = (SavedMajorVersion == 0x0c) ? TRUE : FALSE;
  31. }
  32. /*
  33. * Function: CheckVersion
  34. * Description: Checks the extension DLL version against the target version.
  35. * Author: Created by shouse, 1.4.01 - copied largely from ndiskd.dll
  36. */
  37. VOID CheckVersion (VOID) {
  38. /* For now, do nothing. */
  39. return;
  40. #if DBG
  41. if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  42. dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
  43. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  44. }
  45. #else
  46. if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  47. dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
  48. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  49. }
  50. #endif
  51. }
  52. /*
  53. * Function: ExtensionApiVersion
  54. * Description: Returns the API version information.
  55. * Author: Created by shouse, 1.4.01 - copied largely from ndiskd.dll
  56. */
  57. LPEXT_API_VERSION ExtensionApiVersion (VOID) {
  58. return &ApiVersion;
  59. }
  60. /*
  61. * Function: help
  62. * Description: Prints the usage of the NLB KD debugger extensions.
  63. * Author: Created by shouse, 1.4.01
  64. */
  65. DECLARE_API (help) {
  66. dprintf("Network Load Balancing debugger extensions:\n");
  67. dprintf(" version print nlbkd version\n");
  68. dprintf(" nlbadapters [Verbosity] show all NLB adapter blocks\n");
  69. dprintf(" nlbadapter <Adapter Block> [Verbosity] dump an NLB adapter block\n");
  70. dprintf(" nlbctxt <Context Block> [Verbosity] dump an NLB context block\n");
  71. dprintf(" nlbload <Load Block> [Verbosity] dump an NLB load block\n");
  72. dprintf(" nlbparams <Params Block> [Verbosity] dump an NLB parameters block\n");
  73. dprintf(" nlbresp <Packet> [Direction] dump the NLB private data for the specified packet\n");
  74. dprintf(" nlbpkt <Packet> [RC Port] dump an NDIS packet whose content is determined\n");
  75. dprintf(" on the fly (IP, UDP, TCP, heartbeat, IGMP, remote-control, etc)\n");
  76. dprintf(" nlbether <Ether Frame> [RC Port] dump an ethernet frame. Uses same technique as nlbpkt\n");
  77. dprintf(" nlbip <IP Packet> [RC Port] dump an IP packet. Uses same technique as nlbpkt\n");
  78. dprintf(" nlbteams dump the linked list of NLB BDA teams\n");
  79. dprintf(" nlbhooks dump the global NLB hook information\n");
  80. dprintf(" nlbmac <Context Block> dump the MAC address lists (unicast and multicast) for the physical\n");
  81. dprintf(" adapter to which this NLB instance is bound\n");
  82. dprintf(" nlbdscr <Descriptor> dump the contents of a connection descriptor\n");
  83. dprintf(" nlbconnq <Queue>[Index] [MaxEntries] dump the contents of a connection descriptor queue\n");
  84. dprintf(" nlbglobalq <Queue>[Index] [MaxEntries] dump the contents of a global connection descriptor queue\n");
  85. dprintf(" nlbfilter <pointer to context block> <protocol> <client IP>[:<client port>] <server IP>[:<server port>] [flags]\n");
  86. dprintf(" query map function and retrieve any existing state for this tuple\n");
  87. dprintf(" nlbhash <Context Block> <Packet> determine whether or not NLB will accept this packet\n");
  88. dprintf("\n");
  89. dprintf(" [Verbosity] is an optional integer from 0 to 2 that determines the level of detail displayed.\n");
  90. dprintf(" [Direction] is an optional integer that specifies the direction of the packet (RCV=0, SND=1).\n");
  91. dprintf(" [RC Port] is an optional UDP port used to identify whether a UDP packet might be for remote-control.\n");
  92. dprintf(" [Flags] is an optional TCP-like packet type specification; SYN, FIN or RST.\n");
  93. dprintf(" [MaxEntries] is an optional maximum number of entries to print (default is 10)\n");
  94. dprintf(" [Index] is an optional queue index which can be used if the queue pointer points to an array of queues.\n");
  95. dprintf(" The index should be specified in Addr[index], Addr{index} or Addr(index) form.\n");
  96. dprintf("\n");
  97. dprintf(" IP addresses can be in dotted notation or network byte order DWORDs.\n");
  98. dprintf(" I.e., 169.128.0.101 = 0x650080a9 (in x86 memory = A9 80 00 65)\n");
  99. dprintf(" Valid protocols include TCP, UDP, IPSec and GRE.\n");
  100. }
  101. /*
  102. * Function: version
  103. * Description: Prints the NLB KD debugger extension version information.
  104. * Author: Created by shouse, 1.4.01 - copied largely from ndiskd.dll
  105. */
  106. DECLARE_API (version) {
  107. #if DBG
  108. PCSTR kind = "Checked";
  109. #else
  110. PCSTR kind = "Free";
  111. #endif
  112. dprintf("%s NLB Extension DLL for Build %d debugging %s kernel for Build %d\n", kind,
  113. VER_PRODUCTBUILD, SavedMajorVersion == 0x0c ? "Checked" : "Free", SavedMinorVersion);
  114. }
  115. /*
  116. * Function: nlbadapters
  117. * Description: Prints all NLB adapter strucutres in use. Verbosity is always LOW.
  118. * Author: Created by shouse, 1.5.01
  119. */
  120. DECLARE_API (nlbadapters) {
  121. ULONG dwVerbosity = VERBOSITY_LOW;
  122. CHAR szArgList[10][MAX_PATH];
  123. CHAR szArgBuffer[MAX_PATH];
  124. ULONG64 pNumAdapters;
  125. DWORD dwAdapterSize;
  126. ULONG dwNumAdapters;
  127. ULONG64 pAdapter;
  128. ULONG dwIndex;
  129. INT index = 0;
  130. CHAR * p;
  131. if (args && (*args)) {
  132. /* Copy the argument list into a temporary buffer. */
  133. strcpy(szArgBuffer, args);
  134. /* Peel out all of the tokenized strings. */
  135. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  136. strcpy(&szArgList[index++][0], p);
  137. /* If a verbosity was specified, get it. */
  138. if (index == 1) dwVerbosity = atoi(&szArgList[0][0]);
  139. /* If too many arguments were given, or the verbosity was out of range, complain. */
  140. if ((index > 1) || (dwVerbosity > VERBOSITY_HIGH)) {
  141. PrintUsage(USAGE_ADAPTERS);
  142. return;
  143. }
  144. }
  145. /* Get the address of the global variable containing the number of NLB adapters in use. */
  146. pNumAdapters = GetExpression(UNIV_ADAPTERS_COUNT);
  147. if (!pNumAdapters) {
  148. ErrorCheckSymbols(UNIV_ADAPTERS_COUNT);
  149. return;
  150. }
  151. /* Get the number of adapters from the address. */
  152. dwNumAdapters = GetUlongFromAddress(pNumAdapters);
  153. dprintf("Network Load Balancing is currently bound to %u adapter(s).\n", dwNumAdapters);
  154. /* Get the base address of the global array of NLB adapter structures. */
  155. pAdapter = GetExpression(UNIV_ADAPTERS);
  156. if (!pAdapter) {
  157. ErrorCheckSymbols(UNIV_ADAPTERS);
  158. return;
  159. }
  160. /* Find out the size of a MAIN_ADAPTER structure. */
  161. dwAdapterSize = GetTypeSize(MAIN_ADAPTER);
  162. /* Loop through all adapters in use and print some information about them. */
  163. for (dwIndex = 0; dwIndex < CVY_MAX_ADAPTERS; dwIndex++) {
  164. ULONG dwValue;
  165. /* Retrieve the used/unused state of the adapter. */
  166. GetFieldValue(pAdapter, MAIN_ADAPTER, MAIN_ADAPTER_FIELD_USED, dwValue);
  167. /* If the adapter is in use, or the user specified HIGH verbosity, print the adapter. */
  168. if (dwValue || (dwVerbosity == VERBOSITY_HIGH)) {
  169. /* Print the adapter index. */
  170. dprintf("\n[%u] ", dwIndex);
  171. /* Print the adapter contents. If verbosity is high, change it to
  172. medium - we don't want to recurse into context from here. */
  173. PrintAdapter(pAdapter, (dwVerbosity == VERBOSITY_HIGH) ? VERBOSITY_MEDIUM : dwVerbosity);
  174. }
  175. /* Advance the pointer to the next index in the array of structures. */
  176. pAdapter += dwAdapterSize;
  177. }
  178. }
  179. /*
  180. * Function: nlbadapter
  181. * Description: Prints NLB adapter information. Takes an adapter pointer and an
  182. * optional verbosity as arguments. Default verbosity is MEDIUM.
  183. * Author: Created by shouse, 1.5.01
  184. */
  185. DECLARE_API (nlbadapter) {
  186. ULONG dwVerbosity = VERBOSITY_LOW;
  187. CHAR szArgList[10][MAX_PATH];
  188. CHAR szArgBuffer[MAX_PATH];
  189. ULONG64 pAdapter;
  190. INT index = 0;
  191. CHAR * p;
  192. /* Make sure at least one argument, the adapter pointer, is there. */
  193. if (!args || !(*args)) {
  194. PrintUsage(USAGE_ADAPTER);
  195. return;
  196. }
  197. /* Get the address of the NLB adapter block from the command line. */
  198. pAdapter = (ULONG64)GetExpression(args);
  199. /* Copy the argument list into a temporary buffer. */
  200. strcpy(szArgBuffer, args);
  201. /* Peel out all of the tokenized strings. */
  202. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  203. strcpy(&szArgList[index++][0], p);
  204. /* If a verbosity was specified, get it. */
  205. if (index == 2) dwVerbosity = atoi(&szArgList[1][0]);
  206. /* If too many arguments were given, or the verbosity was out of range, complain. */
  207. if ((index > 2) || (dwVerbosity > VERBOSITY_HIGH)) {
  208. PrintUsage(USAGE_ADAPTER);
  209. return;
  210. }
  211. /* Print the adapter contents. */
  212. PrintAdapter(pAdapter, dwVerbosity);
  213. }
  214. /*
  215. * Function: nlbctxt
  216. * Description: Prints NLB context information. Takes a context pointer and an
  217. * optional verbosity as arguments. Default verbosity is LOW.
  218. * Author: Created by shouse, 1.21.01
  219. */
  220. DECLARE_API (nlbctxt) {
  221. ULONG dwVerbosity = VERBOSITY_LOW;
  222. CHAR szArgList[10][MAX_PATH];
  223. CHAR szArgBuffer[MAX_PATH];
  224. ULONG64 pContext;
  225. INT index = 0;
  226. CHAR * p;
  227. /* Make sure at least one argument, the context pointer, is there. */
  228. if (!args || !(*args)) {
  229. PrintUsage(USAGE_CONTEXT);
  230. return;
  231. }
  232. /* Get the address of the NLB context block from the command line. */
  233. pContext = (ULONG64)GetExpression(args);
  234. /* Copy the argument list into a temporary buffer. */
  235. strcpy(szArgBuffer, args);
  236. /* Peel out all of the tokenized strings. */
  237. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  238. strcpy(&szArgList[index++][0], p);
  239. /* If a verbosity was specified, get it. */
  240. if (index == 2) dwVerbosity = atoi(&szArgList[1][0]);
  241. /* If too many arguments were given, or the verbosity was out of range, complain. */
  242. if ((index > 2) || (dwVerbosity > VERBOSITY_HIGH)) {
  243. PrintUsage(USAGE_CONTEXT);
  244. return;
  245. }
  246. /* Print the context contents. */
  247. PrintContext(pContext, dwVerbosity);
  248. }
  249. /*
  250. * Function: nlbload
  251. * Description: Prints NLB load information. Takes a load pointer and an optional
  252. * verbosity as arguments. Default verbosity is LOW.
  253. * Author: Created by shouse, 2.1.01
  254. */
  255. DECLARE_API (nlbload) {
  256. ULONG dwVerbosity = VERBOSITY_LOW;
  257. CHAR szArgList[10][MAX_PATH];
  258. CHAR szArgBuffer[MAX_PATH];
  259. ULONG64 pLoad;
  260. INT index = 0;
  261. CHAR * p;
  262. /* Make sure at least one argument, the load pointer, is there. */
  263. if (!args || !(*args)) {
  264. PrintUsage(USAGE_LOAD);
  265. return;
  266. }
  267. /* Get the address of the NLB load block from the command line. */
  268. pLoad = (ULONG64)GetExpression(args);
  269. /* Copy the argument list into a temporary buffer. */
  270. strcpy(szArgBuffer, args);
  271. /* Peel out all of the tokenized strings. */
  272. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  273. strcpy(&szArgList[index++][0], p);
  274. /* If a verbosity was specified, get it. */
  275. if (index == 2) dwVerbosity = atoi(&szArgList[1][0]);
  276. /* If too many arguments were given, or the verbosity was out of range, complain. */
  277. if ((index > 2) || (dwVerbosity > VERBOSITY_HIGH)) {
  278. PrintUsage(USAGE_LOAD);
  279. return;
  280. }
  281. /* Print the load contents. */
  282. PrintLoad(pLoad, dwVerbosity);
  283. }
  284. /*
  285. * Function: nlbparams
  286. * Description: Prints NLB parameter information. Takes a parameter pointer and an
  287. * optional verbosity as arguments. Default verbosity is LOW.
  288. * Author: Created by shouse, 1.21.01
  289. */
  290. DECLARE_API (nlbparams) {
  291. ULONG dwVerbosity = VERBOSITY_LOW;
  292. CHAR szArgList[10][MAX_PATH];
  293. CHAR szArgBuffer[MAX_PATH];
  294. ULONG64 pParams;
  295. INT index = 0;
  296. CHAR * p;
  297. /* Make sure at least one argument, the params pointer, is there. */
  298. if (!args || !(*args)) {
  299. PrintUsage(USAGE_PARAMS);
  300. return;
  301. }
  302. /* Get the address of the NLB params block from the command line. */
  303. pParams = (ULONG64)GetExpression(args);
  304. /* Copy the argument list into a temporary buffer. */
  305. strcpy(szArgBuffer, args);
  306. /* Peel out all of the tokenized strings. */
  307. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  308. strcpy(&szArgList[index++][0], p);
  309. /* If a verbosity was specified, get it. */
  310. if (index == 2) dwVerbosity = atoi(&szArgList[1][0]);
  311. /* If too many arguments were given, or the verbosity was out of range, complain. */
  312. if ((index > 2) || (dwVerbosity > VERBOSITY_HIGH)) {
  313. PrintUsage(USAGE_PARAMS);
  314. return;
  315. }
  316. /* Print the parameter contents. */
  317. PrintParams(pParams, dwVerbosity);
  318. }
  319. /*
  320. * Function: nlbresp
  321. * Description: Prints out the NLB private packet data for a given packet. Takes a
  322. * packet pointer and an optional direction as arguments. If not specified,
  323. * the packet is presumed to be on the receive path.
  324. * Author: Created by shouse, 1.31.01
  325. */
  326. DECLARE_API (nlbresp) {
  327. ULONG dwDirection = DIRECTION_RECEIVE;
  328. CHAR szArgList[10][MAX_PATH];
  329. CHAR szArgBuffer[MAX_PATH];
  330. ULONG64 pPacket;
  331. INT index = 0;
  332. CHAR * p;
  333. /* Make sure at least one argument, the packet pointer, is there. */
  334. if (!args || !(*args)) {
  335. PrintUsage(USAGE_RESP);
  336. return;
  337. }
  338. /* Get the address of the NDIS packet from the command line. */
  339. pPacket = (ULONG64)GetExpression(args);
  340. /* Copy the argument list into a temporary buffer. */
  341. strcpy(szArgBuffer, args);
  342. /* Peel out all of the tokenized strings. */
  343. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  344. strcpy(&szArgList[index++][0], p);
  345. /* If a direction was specified, get it. */
  346. if (index == 2) dwDirection = atoi(&szArgList[1][0]);
  347. /* If too many arguments were given, or the direction was out of range, complain. */
  348. if ((index > 2) || (dwDirection > DIRECTION_SEND)) {
  349. PrintUsage(USAGE_RESP);
  350. return;
  351. }
  352. /* Print the NLB private data buffer contents. */
  353. PrintResp(pPacket, dwDirection);
  354. }
  355. /*
  356. * Function: nlbpkt
  357. * Description: Prints out the contents of an NDIS packet. Takes a packet
  358. * pointer as an argument.
  359. * Author: Created by chrisdar 2001.10.11
  360. */
  361. DECLARE_API (nlbpkt) {
  362. CHAR szArgList[10][MAX_PATH];
  363. CHAR szArgBuffer[MAX_PATH];
  364. ULONG64 pPkt;
  365. INT index = 0;
  366. CHAR * p;
  367. NETWORK_DATA nd;
  368. /* Make sure at least one argument, the queue pointer, is there. */
  369. if (!args || !(*args)) {
  370. PrintUsage(USAGE_PKT);
  371. return;
  372. }
  373. /* Get the address of the queue from the command line. */
  374. pPkt = (ULONG64)GetExpression(args);
  375. /* Copy the argument list into a temporary buffer. */
  376. strcpy(szArgBuffer, args);
  377. /* Peel out all of the tokenized strings. */
  378. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  379. strcpy(&szArgList[index++][0], p);
  380. /* If the wrong number of arguments were given, complain. */
  381. if (index > 2 || index < 1) {
  382. PrintUsage(USAGE_PKT);
  383. return;
  384. }
  385. /* Clear out the network data structure. */
  386. ZeroMemory(&nd, sizeof(nd));
  387. nd.UserRCPort = CVY_DEF_RCT_PORT;
  388. if (index > 1)
  389. {
  390. nd.UserRCPort = atoi(&szArgList[1][0]);
  391. }
  392. if (nd.UserRCPort > CVY_MAX_PORT)
  393. {
  394. dprintf("Invalid port: %s\n", nd.UserRCPort);
  395. return;
  396. }
  397. /* Parse through the NDIS packet and retrieve the packet contents. */
  398. {
  399. UCHAR RawData[CVY_MAX_FRAME_SIZE + ETHER_HEADER_SIZE];
  400. ULONG BytesRead = 0;
  401. ULONG64 pHBData;
  402. /* Parse the buffers in the NDIS packet and get the raw packet data out. We get
  403. a pointer to the heartbeat data in machine memory, not debugger process memory
  404. because for all other packets, we read from temporary stack space in the debugger
  405. - RawData - but for heartbeats, we read directly from kernel memory space (only
  406. because a function to do so already exits - no need to write another). */
  407. BytesRead = ParseNDISPacket(pPkt, RawData, CVY_MAX_FRAME_SIZE + ETHER_HEADER_SIZE, &pHBData);
  408. /* If some packet contents was successfully read, continue to process the packet. */
  409. if (BytesRead != 0) {
  410. /* Parse the Ethernet packet and store the information parsed in the NETWORK_DATA
  411. structure. Note that this function recurses to also fill in IP, TCP/UDP,
  412. heartbeat, remote control, etc. information as well. */
  413. PopulateEthernet(pHBData, RawData, BytesRead, &nd);
  414. /* Print the packet, including IP and TCP data (if present), or heartbeat
  415. or remote control information, etc. */
  416. dprintf("NDIS Packet 0x%p\n", pPkt);
  417. PrintPacket(&nd);
  418. }
  419. }
  420. }
  421. /*
  422. * Function: nlbether
  423. * Description: Prints out the contents of an ethernet packet. Takes a packet
  424. * pointer as an argument.
  425. * Author: Created by chrisdar 2001.10.11
  426. */
  427. DECLARE_API (nlbether){
  428. CHAR szArgList[10][MAX_PATH];
  429. CHAR szArgBuffer[MAX_PATH];
  430. ULONG64 pPkt;
  431. INT index = 0;
  432. CHAR * p;
  433. ULONG BytesRead;
  434. UCHAR RawData[CVY_MAX_FRAME_SIZE];
  435. BOOL b;
  436. NETWORK_DATA nd;
  437. /* Make sure at least one argument, the queue pointer, is there. */
  438. if (!args || !(*args)) {
  439. PrintUsage(USAGE_ETHER);
  440. return;
  441. }
  442. /* Get the address of the queue from the command line. */
  443. pPkt = (ULONG64)GetExpression(args);
  444. /* Copy the argument list into a temporary buffer. */
  445. strcpy(szArgBuffer, args);
  446. /* Peel out all of the tokenized strings. */
  447. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  448. strcpy(&szArgList[index++][0], p);
  449. /* If the wrong number of arguments were given, complain. */
  450. if (index > 2 || index < 1) {
  451. PrintUsage(USAGE_ETHER);
  452. return;
  453. }
  454. ZeroMemory(&nd, sizeof(nd));
  455. nd.UserRCPort = CVY_DEF_RCT_PORT;
  456. if (index > 1)
  457. {
  458. nd.UserRCPort = atoi(&szArgList[1][0]);
  459. }
  460. if (nd.UserRCPort > CVY_MAX_PORT)
  461. {
  462. dprintf("Invalid port: %s\n", nd.UserRCPort);
  463. return;
  464. }
  465. b = ReadMemory(pPkt, RawData, CVY_MAX_FRAME_SIZE, &BytesRead);
  466. if (!b || BytesRead != CVY_MAX_FRAME_SIZE)
  467. {
  468. dprintf("Unable to read %u bytes at address %p\n", CVY_MAX_FRAME_SIZE, pPkt);
  469. }
  470. else
  471. {
  472. PopulateEthernet(pPkt + ETHER_HEADER_SIZE + GetTypeSize(MAIN_FRAME_HDR),
  473. RawData,
  474. CVY_MAX_FRAME_SIZE,
  475. &nd
  476. );
  477. /* Print the NLB private data buffer contents. */
  478. dprintf("Ethernet Packet 0x%p\n", pPkt);
  479. PrintPacket(&nd);
  480. }
  481. }
  482. /*
  483. * Function: nlbip
  484. * Description: Prints out the contents of an ip packet. Takes a packet
  485. * pointer as an argument.
  486. * Author: Created by chrisdar 2001.10.11
  487. */
  488. DECLARE_API (nlbip){
  489. CHAR szArgList[10][MAX_PATH];
  490. CHAR szArgBuffer[MAX_PATH];
  491. INT index = 0;
  492. CHAR * p;
  493. ULONG64 pPkt;
  494. ULONG BytesRead;
  495. UCHAR RawData[CVY_MAX_FRAME_SIZE];
  496. BOOL b;
  497. NETWORK_DATA nd;
  498. /* Make sure at least one argument, the queue pointer, is there. */
  499. if (!args || !(*args)) {
  500. PrintUsage(USAGE_IP);
  501. return;
  502. }
  503. /* Get the address of the queue from the command line. */
  504. pPkt = (ULONG64)GetExpression(args);
  505. /* Copy the argument list into a temporary buffer. */
  506. strcpy(szArgBuffer, args);
  507. /* Peel out all of the tokenized strings. */
  508. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  509. strcpy(&szArgList[index++][0], p);
  510. /* If the wrong number of arguments were given, complain. */
  511. if (index > 2 || index < 1) {
  512. PrintUsage(USAGE_IP);
  513. return;
  514. }
  515. ZeroMemory(&nd, sizeof(nd));
  516. nd.UserRCPort = CVY_DEF_RCT_PORT;
  517. if (index > 1)
  518. {
  519. nd.UserRCPort = atoi(&szArgList[1][0]);
  520. }
  521. if (nd.UserRCPort > CVY_MAX_PORT)
  522. {
  523. dprintf("Invalid port: %s\n", nd.UserRCPort);
  524. return;
  525. }
  526. b = ReadMemory(pPkt, RawData, CVY_MAX_FRAME_SIZE, &BytesRead);
  527. if (!b || BytesRead != CVY_MAX_FRAME_SIZE)
  528. {
  529. dprintf("Unable to read %u bytes at address %p\n", CVY_MAX_FRAME_SIZE, pPkt);
  530. }
  531. else
  532. {
  533. PopulateIP(RawData, CVY_MAX_FRAME_SIZE, 0, &nd);
  534. /* Print the NLB private data buffer contents. */
  535. dprintf("IP Packet 0x%p\n", pPkt);
  536. PrintIP(&nd);
  537. }
  538. }
  539. /*
  540. * Function: nlbteams
  541. * Description: Prints all configured Bi-directional Affintiy (BDA) teams.
  542. * Author: Created by shouse, 1.5.01
  543. */
  544. DECLARE_API (nlbteams) {
  545. ULONG64 pTeam;
  546. ULONG64 pAddr;
  547. ULONG dwNumTeams = 0;
  548. ULONG dwValue;
  549. /* No command line arguments should be given. */
  550. if (args && (*args)) {
  551. PrintUsage(USAGE_TEAMS);
  552. return;
  553. }
  554. /* Get the base address of the global linked list of BDA teams. */
  555. pAddr = GetExpression(UNIV_BDA_TEAMS);
  556. if (!pAddr) {
  557. ErrorCheckSymbols(UNIV_BDA_TEAMS);
  558. return;
  559. }
  560. /* Get the pointer to the first team. */
  561. pTeam = GetPointerFromAddress(pAddr);
  562. dprintf("NLB bi-directional affinity teams:\n");
  563. /* Loop through all teams in the list and print them out. */
  564. while (pTeam) {
  565. /* Increment the number of teams found - only used if none are found. */
  566. dwNumTeams++;
  567. dprintf("\n");
  568. /* Print out the team. */
  569. PrintBDATeam(pTeam);
  570. /* Get the offset of the params pointer. */
  571. if (GetFieldOffset(BDA_TEAM, BDA_TEAM_FIELD_NEXT, &dwValue))
  572. dprintf("Can't get offset of %s in %s\n", BDA_TEAM_FIELD_NEXT, BDA_TEAM);
  573. else {
  574. pAddr = pTeam + dwValue;
  575. /* Retrieve the pointer. */
  576. pTeam = GetPointerFromAddress(pAddr);
  577. }
  578. }
  579. if (!dwNumTeams) dprintf("\nNone.\n");
  580. }
  581. /*
  582. * Function: nlbhooks
  583. * Description: Prints the global NLB hook function information.
  584. * Author: Created by shouse, 12.20.01
  585. */
  586. DECLARE_API (nlbhooks) {
  587. ULONG64 pAddr;
  588. /* No command line arguments should be given. */
  589. if (args && (*args)) {
  590. PrintUsage(USAGE_HOOKS);
  591. return;
  592. }
  593. /* Get the base address of the global linked list of BDA teams. */
  594. pAddr = GetExpression(UNIV_HOOKS);
  595. if (!pAddr) {
  596. ErrorCheckSymbols(UNIV_HOOKS);
  597. return;
  598. }
  599. dprintf("NLB kernel-mode hooks:\n");
  600. /* Print the global NLB hook configuration and state. */
  601. PrintHooks(pAddr);
  602. }
  603. /*
  604. * Function: nlbmac
  605. * Description: Prints the unicast MAC address and all multicast MAC addresses
  606. * configured on the adapter to which this instance of NLB is bound.
  607. * Author: Created by shouse, 1.8.02
  608. */
  609. DECLARE_API (nlbmac) {
  610. CHAR szArgList[10][MAX_PATH];
  611. CHAR szArgBuffer[MAX_PATH];
  612. ULONG64 pContext;
  613. INT index = 0;
  614. CHAR * p;
  615. /* Make sure at least one argument, the context pointer, is there. */
  616. if (!args || !(*args)) {
  617. PrintUsage(USAGE_MAC);
  618. return;
  619. }
  620. /* Get the address of the NLB context block from the command line. */
  621. pContext = (ULONG64)GetExpression(args);
  622. /* Copy the argument list into a temporary buffer. */
  623. strcpy(szArgBuffer, args);
  624. /* Peel out all of the tokenized strings. */
  625. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  626. strcpy(&szArgList[index++][0], p);
  627. /* If too many arguments were given, complain. */
  628. if (index > 1) {
  629. PrintUsage(USAGE_MAC);
  630. return;
  631. }
  632. /* Print the context contents. */
  633. PrintNetworkAddresses(pContext);
  634. }
  635. /*
  636. * Function: nlbdscr
  637. * Description: Prints the contents of an NLB connection descriptor.
  638. * Author: Created by shouse, 1.8.02
  639. */
  640. DECLARE_API (nlbdscr) {
  641. CHAR szArgList[10][MAX_PATH];
  642. CHAR szArgBuffer[MAX_PATH];
  643. ULONG64 pDescriptor;
  644. INT index = 0;
  645. CHAR * p;
  646. /* Make sure at least one argument, the descriptor pointer, is there. */
  647. if (!args || !(*args)) {
  648. PrintUsage(USAGE_DSCR);
  649. return;
  650. }
  651. /* Get the address of the connection descriptor from the command line. */
  652. pDescriptor = (ULONG64)GetExpression(args);
  653. /* Copy the argument list into a temporary buffer. */
  654. strcpy(szArgBuffer, args);
  655. /* Peel out all of the tokenized strings. */
  656. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  657. strcpy(&szArgList[index++][0], p);
  658. /* If too many arguments were given, complain. */
  659. if (index > 1) {
  660. PrintUsage(USAGE_DSCR);
  661. return;
  662. }
  663. /* Print the context contents. */
  664. PrintConnectionDescriptor(pDescriptor);
  665. }
  666. /*
  667. * Function: nlbconnq
  668. * Description: This function prints out all connection descriptors in a given
  669. * queue of descriptors.
  670. * Author: Created by shouse, 4.15.01
  671. */
  672. DECLARE_API (nlbconnq) {
  673. ULONG dwMaxEntries = 10;
  674. ULONG dwIndex = 0;
  675. CHAR szArgList[10][MAX_PATH];
  676. CHAR szArgBuffer[MAX_PATH];
  677. ULONG64 pQueue;
  678. INT index = 0;
  679. CHAR * p;
  680. /* Make sure at least one argument, the queue pointer, is there. */
  681. if (!args || !(*args)) {
  682. PrintUsage(USAGE_CONNQ);
  683. return;
  684. }
  685. /* Copy the argument list into a temporary buffer. */
  686. strcpy(szArgBuffer, args);
  687. /* Peel out all of the tokenized strings. */
  688. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  689. strcpy(&szArgList[index++][0], p);
  690. /* Tokenize the queue address looking for an index. This will return
  691. a pointer to the address whether an index exists or not. */
  692. p = mystrtok(szArgList[0], "[({");
  693. /* Get the address of the queue. */
  694. pQueue = (ULONG64)GetExpression(p);
  695. /* Look for the end of the address index. If no index existed, this will return
  696. NULL. If an index was given, this returns a string containing the index. */
  697. p = mystrtok(NULL, "])}");
  698. if (p) dwIndex = atoi(p);
  699. /* If a maximum number of entries to print was specified, get it. */
  700. if (index == 2) dwMaxEntries = atoi(&szArgList[1][0]);
  701. /* If too many arguments were given, complain. */
  702. if (index > 2) {
  703. PrintUsage(USAGE_CONNQ);
  704. return;
  705. }
  706. /* Print the NLB connection queue. */
  707. PrintQueue(pQueue, dwIndex, dwMaxEntries);
  708. }
  709. /*
  710. * Function: nlbglobalq
  711. * Description: This function prints out all connection descriptors in a given
  712. * global (GLOBAL_CONN_QUEUE) queue of descriptors.
  713. * Author: Created by shouse, 4.15.01
  714. */
  715. DECLARE_API (nlbglobalq) {
  716. ULONG dwMaxEntries = 10;
  717. ULONG dwIndex = 0;
  718. CHAR szArgList[10][MAX_PATH];
  719. CHAR szArgBuffer[MAX_PATH];
  720. ULONG64 pQueue;
  721. INT index = 0;
  722. CHAR * p;
  723. /* Make sure at least one argument, the queue pointer, is there. */
  724. if (!args || !(*args)) {
  725. PrintUsage(USAGE_CONNQ);
  726. return;
  727. }
  728. /* Copy the argument list into a temporary buffer. */
  729. strcpy(szArgBuffer, args);
  730. /* Peel out all of the tokenized strings. */
  731. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  732. strcpy(&szArgList[index++][0], p);
  733. /* Tokenize the queue address looking for an index. This will return
  734. a pointer to the address whether an index exists or not. */
  735. p = mystrtok(szArgList[0], "[({");
  736. /* Get the address of the queue. */
  737. pQueue = (ULONG64)GetExpression(p);
  738. /* Look for the end of the address index. If no index existed, this will return
  739. NULL. If an index was given, this returns a string containing the index. */
  740. p = mystrtok(NULL, "])}");
  741. if (p) dwIndex = atoi(p);
  742. /* If a maximum number of entries to print was specified, get it. */
  743. if (index == 2) dwMaxEntries = atoi(&szArgList[1][0]);
  744. /* If too many arguments were given, complain. */
  745. if (index > 2) {
  746. PrintUsage(USAGE_GLOBALQ);
  747. return;
  748. }
  749. /* Print the NLB global connection queue. */
  750. PrintGlobalQueue(pQueue, dwIndex, dwMaxEntries);
  751. }
  752. /*
  753. * Function: nlbhash
  754. * Description:
  755. * Author: Created by shouse, 4.15.01
  756. */
  757. DECLARE_API (nlbhash) {
  758. CHAR szArgList[10][MAX_PATH];
  759. CHAR szArgBuffer[MAX_PATH];
  760. ULONG64 pContext;
  761. ULONG64 pPkt;
  762. INT index = 0;
  763. CHAR * p;
  764. ULONG dwValue;
  765. ULONG64 pParams;
  766. /* Make sure at least one argument, the queue pointer, is there. */
  767. if (!args || !(*args)) {
  768. PrintUsage(USAGE_HASH);
  769. return;
  770. }
  771. /* Get the address of the queue from the command line. */
  772. pContext = (ULONG64)GetExpression(args);
  773. /* Copy the argument list into a temporary buffer. */
  774. strcpy(szArgBuffer, args);
  775. /* Peel out all of the tokenized strings. */
  776. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  777. strcpy(&szArgList[index++][0], p);
  778. /* If the wrong number of arguments were given, complain. */
  779. if (index != 2) {
  780. PrintUsage(USAGE_HASH);
  781. return;
  782. }
  783. /* Get the pointer to the NDIS packet from the second argument. */
  784. pPkt = (ULONG64)GetExpression(&szArgList[1][0]);
  785. /* Get the MAIN_CTXT_CODE from the structure to make sure that this address
  786. indeed points to a valid NLB context block. */
  787. GetFieldValue(pContext, MAIN_CTXT, MAIN_CTXT_FIELD_CODE, dwValue);
  788. if (dwValue != MAIN_CTXT_CODE) {
  789. dprintf(" Error: Invalid NLB context block. Wrong code found (0x%08x).\n", dwValue);
  790. return;
  791. }
  792. /* Parse through the NDIS packet and retrieve the packet contents. */
  793. {
  794. UCHAR RawData[CVY_MAX_FRAME_SIZE + ETHER_HEADER_SIZE];
  795. ULONG BytesRead = 0;
  796. ULONG64 pHBData;
  797. /* Parse the buffers in the NDIS packet and get the raw packet data out. We get
  798. a pointer to the heartbeat data in machine memory, not debugger process memory
  799. because for all other packets, we read from temporary stack space in the debugger
  800. - RawData - but for heartbeats, we read directly from kernel memory space (only
  801. because a function to do so already exits - no need to write another). */
  802. BytesRead = ParseNDISPacket(pPkt, RawData, CVY_MAX_FRAME_SIZE + ETHER_HEADER_SIZE, &pHBData);
  803. /* If some packet contents was successfully read, continue to process the packet. */
  804. if (BytesRead != 0) {
  805. NETWORK_DATA nd;
  806. /* Clear out the network data structure. */
  807. ZeroMemory(&nd, sizeof(nd));
  808. /* Get the pointer to the NLB parameters. */
  809. GetFieldOffset(MAIN_CTXT, MAIN_CTXT_FIELD_PARAMS, &dwValue);
  810. pParams = pContext + dwValue;
  811. /* Get the remote control port. */
  812. GetFieldValue(pParams, CVY_PARAMS, CVY_PARAMS_FIELD_REMOTE_CONTROL_PORT, dwValue);
  813. /* Set the remote control port in the network data block. */
  814. nd.UserRCPort = dwValue;
  815. /* Parse the Ethernet packet and store the information parsed in the NETWORK_DATA
  816. structure. Note that this function recurses to also fill in IP, TCP/UDP,
  817. heartbeat, remote control, etc. information as well. */
  818. PopulateEthernet(pHBData, RawData, BytesRead, &nd);
  819. /* Print the packet, including IP and TCP data (if present), or heartbeat
  820. or remote control information, etc. */
  821. dprintf("NDIS Packet 0x%p\n", pPkt);
  822. PrintPacket(&nd);
  823. /* Now call into the filtering extension to determine the fate of this packet. */
  824. dprintf("\n");
  825. PrintHash(pContext, &nd);
  826. }
  827. }
  828. }
  829. /*
  830. * Function: nlbfilter
  831. * Description: This function will perform the NLB hashing algorithm to determine
  832. * whether a given packet - identified by a (Src IP, Src port, Dst IP,
  833. * Dst port) tuple would be handled by this host or another host.
  834. * Further, if the connection is a known TCP connection, the associated
  835. * descriptor and state information are displayed.
  836. * Author: Created by shouse, 1.11.02
  837. */
  838. DECLARE_API (nlbfilter) {
  839. CHAR szArgList[10][MAX_PATH];
  840. CHAR szArgBuffer[MAX_PATH];
  841. UCHAR cFlags = NLB_FILTER_FLAGS_CONN_DATA;
  842. ULONG64 pLoad;
  843. ULONG dwClientIPAddress;
  844. ULONG dwClientPort;
  845. ULONG dwServerIPAddress;
  846. ULONG dwServerPort;
  847. USHORT wProtocol;
  848. INT index = 0;
  849. CHAR * p;
  850. /* Make sure that the load pointer is there. */
  851. if (!args || !(*args)) {
  852. PrintUsage(USAGE_FILTER);
  853. return;
  854. }
  855. /* Get the address of the load module from the command line. */
  856. pLoad = (ULONG64)GetExpression(args);
  857. /* Copy the argument list into a temporary buffer. */
  858. strcpy(szArgBuffer, args);
  859. /* Peel out all of the tokenized strings. */
  860. for (p = mystrtok(szArgBuffer, " \t,"); p && *p; p = mystrtok(NULL, " \t,"))
  861. strcpy(&szArgList[index++][0], p);
  862. /* If too many arguments were given, complain. */
  863. if ((index > 5) || (index < 4)) {
  864. PrintUsage(USAGE_FILTER);
  865. return;
  866. }
  867. /* Find the protocol specification. */
  868. if (!_stricmp(szArgList[1], "TCP")) {
  869. wProtocol = TCPIP_PROTOCOL_TCP;
  870. } else if (!_stricmp(szArgList[1], "UDP")) {
  871. wProtocol = TCPIP_PROTOCOL_UDP;
  872. } else if (!_stricmp(szArgList[1], "IPSec")) {
  873. wProtocol = TCPIP_PROTOCOL_IPSEC1;
  874. } else if (!_stricmp(szArgList[1], "PPTP")) {
  875. wProtocol = TCPIP_PROTOCOL_PPTP;
  876. } else if (!_stricmp(szArgList[1], "GRE")) {
  877. wProtocol = TCPIP_PROTOCOL_GRE;
  878. } else if (!_stricmp(szArgList[1], "ICMP")) {
  879. wProtocol = TCPIP_PROTOCOL_ICMP;
  880. } else {
  881. dprintf("Invalid protocol: %s\n", szArgList[1]);
  882. return;
  883. }
  884. /* The client port defaults to unspecified. */
  885. dwClientPort = 0;
  886. /* If we find a colon in the client specification, then we expect that
  887. its an IP:port specification. */
  888. p = strchr(szArgList[2], ':');
  889. /* If we found the port string, separate the IP from the string with
  890. a NUL character and extract the port value. */
  891. if (p != NULL) {
  892. *p = UNICODE_NULL;
  893. p++;
  894. dwClientPort = atoi(p);
  895. /* Make sure the port is between 1 and 65535. */
  896. if ((dwClientPort == 0) || (dwClientPort > CVY_MAX_PORT)) {
  897. dprintf("Invalid port: %s\n", dwClientPort);
  898. return;
  899. }
  900. }
  901. /* If we find a '.' in the IP address, then we need to convert it using inet_addr.
  902. If there is no '.', then we assume its already a DWORD in network byte order. */
  903. if (strchr(szArgList[2], '.'))
  904. dwClientIPAddress = inet_addr(szArgList[2]);
  905. else
  906. dwClientIPAddress = (ULONG)GetExpression(&szArgList[2][0]);
  907. /* The server port defaults to unspecified. */
  908. dwServerPort = 0;
  909. /* If we find a colon in the server specification, then we expect that
  910. its an IP:port specification. */
  911. p = strchr(szArgList[3], ':');
  912. /* If we found the port string, separate the IP from the string with
  913. a NUL character and extract the port value. */
  914. if (p != NULL) {
  915. *p = UNICODE_NULL;
  916. p++;
  917. dwServerPort = atoi(p);
  918. /* Make sure the port is between 1 and 65535. */
  919. if ((dwServerPort == 0) || (dwServerPort > CVY_MAX_PORT)) {
  920. dprintf("Invalid port: %s\n", dwServerPort);
  921. return;
  922. }
  923. }
  924. /* If we find a '.' in the IP address, then we need to convert it using inet_addr.
  925. If there is no '.', then we assume its already a DWORD in network byte order. */
  926. if (strchr(szArgList[3], '.'))
  927. dwServerIPAddress = inet_addr(szArgList[3]);
  928. else
  929. dwServerIPAddress = (ULONG)GetExpression(&szArgList[3][0]);
  930. cFlags = NLB_FILTER_FLAGS_CONN_DATA;
  931. /* If an seventh argument has been specified, it is TCP packet type, which should be SYN, DATA, FIN or RST. */
  932. if (index >= 5) {
  933. if (!_stricmp(szArgList[4], "SYN")) {
  934. cFlags |= NLB_FILTER_FLAGS_CONN_UP;
  935. } else if (!_stricmp(szArgList[4], "FIN")) {
  936. cFlags |= NLB_FILTER_FLAGS_CONN_DOWN;
  937. } else if (!_stricmp(szArgList[4], "RST")) {
  938. cFlags |= NLB_FILTER_FLAGS_CONN_RESET;
  939. } else {
  940. dprintf("Invalid connection flags: %s\n", szArgList[4]);
  941. return;
  942. }
  943. }
  944. switch (wProtocol) {
  945. case TCPIP_PROTOCOL_TCP:
  946. if (dwServerPort == 0) {
  947. dprintf("A server port is required\n");
  948. return;
  949. }
  950. if (dwClientPort == 0)
  951. {
  952. if ((cFlags == NLB_FILTER_FLAGS_CONN_DOWN) ||
  953. (cFlags == NLB_FILTER_FLAGS_CONN_RESET))
  954. {
  955. dprintf("RST/FIN filtering requires a client port\n");
  956. return;
  957. }
  958. else
  959. {
  960. cFlags = NLB_FILTER_FLAGS_CONN_UP;
  961. }
  962. }
  963. if (dwServerPort != PPTP_CTRL_PORT)
  964. {
  965. break;
  966. }
  967. wProtocol = TCPIP_PROTOCOL_PPTP;
  968. /* This fall-through is INTENTIONAL. In this case, we're verified the TCP
  969. parameters, but discovered that because the server port was 1723, this
  970. is actually PPTP, so force it through the PPTP verification as well. */
  971. case TCPIP_PROTOCOL_PPTP:
  972. dwServerPort = PPTP_CTRL_PORT;
  973. if (dwClientPort == 0)
  974. {
  975. if ((cFlags == NLB_FILTER_FLAGS_CONN_DOWN) ||
  976. (cFlags == NLB_FILTER_FLAGS_CONN_RESET))
  977. {
  978. dprintf("RST/FIN filtering requires a client port\n");
  979. return;
  980. }
  981. else
  982. {
  983. cFlags = NLB_FILTER_FLAGS_CONN_UP;
  984. }
  985. }
  986. break;
  987. case TCPIP_PROTOCOL_UDP:
  988. if (dwServerPort == 0)
  989. {
  990. dprintf("A server port is required\n");
  991. return;
  992. }
  993. if ((dwServerPort != IPSEC_CTRL_PORT) && (dwServerPort != IPSEC_NAT_PORT))
  994. {
  995. if (cFlags != NLB_FILTER_FLAGS_CONN_DATA)
  996. {
  997. dprintf("Connection flags are not valid for UDP packets\n");
  998. return;
  999. }
  1000. break;
  1001. }
  1002. wProtocol = TCPIP_PROTOCOL_IPSEC1;
  1003. /* This fall-through is INTENTIONAL. In this case, we're verified the TCP
  1004. parameters, but discovered that because the server port was 1723, this
  1005. is actually PPTP, so force it through the PPTP verification as well. */
  1006. case TCPIP_PROTOCOL_IPSEC1:
  1007. if (dwServerPort == 0)
  1008. {
  1009. dwServerPort = IPSEC_CTRL_PORT;
  1010. }
  1011. if (dwServerPort == IPSEC_CTRL_PORT)
  1012. {
  1013. if (dwClientPort == 0)
  1014. {
  1015. dwClientPort = IPSEC_CTRL_PORT;
  1016. }
  1017. if (dwClientPort != IPSEC_CTRL_PORT)
  1018. {
  1019. dprintf("IPSec packets destined for server port 500 must originate from client port 500\n");
  1020. return;
  1021. }
  1022. }
  1023. else if (dwServerPort == IPSEC_NAT_PORT)
  1024. {
  1025. if (dwClientPort == 0)
  1026. {
  1027. dprintf("A client port is required\n");
  1028. return;
  1029. }
  1030. }
  1031. else
  1032. {
  1033. dprintf("IPSec packets are always destined for either port 500 or 4500\n");
  1034. return;
  1035. }
  1036. break;
  1037. case TCPIP_PROTOCOL_GRE:
  1038. if (cFlags != NLB_FILTER_FLAGS_CONN_DATA)
  1039. {
  1040. dprintf("Connection flags are not valid for GRE packets\n");
  1041. return;
  1042. }
  1043. dwServerPort = PPTP_CTRL_PORT;
  1044. dwClientPort = PPTP_CTRL_PORT;
  1045. break;
  1046. case TCPIP_PROTOCOL_ICMP:
  1047. if (cFlags != NLB_FILTER_FLAGS_CONN_DATA)
  1048. {
  1049. dprintf("Connection flags are not valid for ICMP packets\n");
  1050. return;
  1051. }
  1052. dwServerPort = 0;
  1053. dwClientPort = 0;
  1054. break;
  1055. default:
  1056. return;
  1057. }
  1058. /* Hash on this tuple and print the results. */
  1059. PrintFilter(pLoad, dwClientIPAddress, dwClientPort, dwServerIPAddress, dwServerPort, wProtocol, cFlags);
  1060. }