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.

641 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. natc.c
  5. Abstract:
  6. This module contains code for testing the functionality of the NAT.
  7. Author:
  8. Abolade Gbadegesin (t-abolag) 15-July-1997
  9. Revision History:
  10. --*/
  11. extern "C" {
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <winsock2.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <ntddip.h>
  20. #include <mprapi.h>
  21. #include <ipfltinf.h>
  22. #include <iphlpapi.h>
  23. #include <ipnat.h>
  24. #include <routprot.h>
  25. #undef ERROR
  26. #include "debug.h"
  27. #include "prot.h"
  28. }
  29. #define INET_NTOA(a) inet_ntoa(*(struct in_addr*)&(a))
  30. #define MAPPING_FORMAT "%3s %4s %15s/%-5d %15s/%-5d %15s/%-5d %-5d\n"
  31. #define IF_COUNT 3
  32. #define MAKE_ADDRESS(a,b,c,d) \
  33. ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
  34. #define NETORDER_PORT(a) \
  35. ((((a) & 0xFF00) >> 8) | (((a) & 0x00FF) << 8))
  36. ULONG InterfaceIndex;
  37. HANDLE IpHandle = NULL;
  38. HANDLE NatHandle = NULL;
  39. //
  40. // FORWARD DECLARATIONS
  41. //
  42. NTSTATUS
  43. CreateLocalInterface(
  44. ULONG Address,
  45. ULONG Mask
  46. );
  47. VOID
  48. DisplayMapping(
  49. PIP_NAT_SESSION_MAPPING Mapping
  50. );
  51. VOID
  52. DumpBuffer(
  53. PUCHAR Buffer,
  54. ULONG Size
  55. );
  56. LONG __cdecl
  57. main(
  58. LONG argc,
  59. CHAR* argv[]
  60. )
  61. /*++
  62. --*/
  63. {
  64. UCHAR Buffer[256];
  65. UNICODE_STRING DeviceString;
  66. PRTR_INFO_BLOCK_HEADER Header;
  67. LONG i;
  68. LONG j;
  69. IO_STATUS_BLOCK IoStatusBlock;
  70. OBJECT_ATTRIBUTES ObjectAttributes;
  71. ULONG Offset;
  72. NTSTATUS status;
  73. ULONG TocCount;
  74. ULONG TocEntry;
  75. //
  76. // Open the IP driver
  77. //
  78. RtlInitUnicodeString(&DeviceString, DD_IP_DEVICE_NAME);
  79. InitializeObjectAttributes(
  80. &ObjectAttributes, &DeviceString, OBJ_CASE_INSENSITIVE, NULL, NULL
  81. );
  82. status = NtCreateFile(
  83. &IpHandle,
  84. SYNCHRONIZE|FILE_READ_DATA|FILE_WRITE_DATA,
  85. &ObjectAttributes,
  86. &IoStatusBlock,
  87. NULL,
  88. FILE_ATTRIBUTE_NORMAL,
  89. FILE_SHARE_READ|FILE_SHARE_WRITE,
  90. FILE_OPEN_IF,
  91. 0,
  92. NULL,
  93. 0
  94. );
  95. if (!NT_SUCCESS(status)) {
  96. printf("Error 0x%08X opening IP driver.\n", status);
  97. return status;
  98. }
  99. if (argc != 3) {
  100. //
  101. // Open the NAT driver
  102. //
  103. RtlInitUnicodeString(&DeviceString, DD_IP_NAT_DEVICE_NAME);
  104. InitializeObjectAttributes(
  105. &ObjectAttributes, &DeviceString, OBJ_CASE_INSENSITIVE, NULL, NULL
  106. );
  107. status = NtCreateFile(
  108. &NatHandle,
  109. SYNCHRONIZE|FILE_READ_DATA|FILE_WRITE_DATA,
  110. &ObjectAttributes,
  111. &IoStatusBlock,
  112. NULL,
  113. FILE_ATTRIBUTE_NORMAL,
  114. FILE_SHARE_READ|FILE_SHARE_WRITE,
  115. FILE_OPEN_IF,
  116. 0,
  117. NULL,
  118. 0
  119. );
  120. if (!NT_SUCCESS(status)) {
  121. printf("Error 0x%08X opening NAT driver.\n", status);
  122. NtClose(IpHandle);
  123. return status;
  124. }
  125. }
  126. if (argc >= 2 && lstrcmpi(argv[1], "-x") == 0) {
  127. CreateLocalInterface(
  128. argc == 4 ? inet_addr(argv[2]) : 0,
  129. argc == 4 ? inet_addr(argv[3]) : 0
  130. );
  131. }
  132. #if DBG
  133. for (;;) {
  134. ULONG Option = 0;
  135. printf("0. Quit\n");
  136. printf("1. Get Interface Info\n");
  137. printf("2. Get Interface Statistics\n");
  138. printf("3. Enumerate Session Mappings\n");
  139. scanf("%d", &Option);
  140. if (!Option) { break; }
  141. if (!InterfaceIndex) {
  142. printf("Enter interface index: ");
  143. scanf("%d", &InterfaceIndex);
  144. }
  145. switch(Option) {
  146. case 1: {
  147. PUCHAR Buffer;
  148. IP_NAT_INTERFACE_INFO InterfaceInfo;
  149. ULONG Size;
  150. InterfaceInfo.Index = InterfaceIndex;
  151. status = NtDeviceIoControlFile(
  152. NatHandle,
  153. NULL,
  154. NULL,
  155. NULL,
  156. &IoStatusBlock,
  157. IOCTL_IP_NAT_GET_INTERFACE_INFO,
  158. (PVOID)&InterfaceInfo,
  159. sizeof(InterfaceInfo),
  160. NULL,
  161. 0
  162. );
  163. if (!NT_SUCCESS(status)) {
  164. printf("status: 0x%08X\n", status);
  165. break;
  166. }
  167. printf(
  168. "Allocating %d bytes\n",
  169. Size = (ULONG)IoStatusBlock.Information
  170. );
  171. Buffer = (PUCHAR)malloc(Size);
  172. status = NtDeviceIoControlFile(
  173. NatHandle,
  174. NULL,
  175. NULL,
  176. NULL,
  177. &IoStatusBlock,
  178. IOCTL_IP_NAT_GET_INTERFACE_INFO,
  179. (PVOID)&InterfaceInfo,
  180. sizeof(InterfaceInfo),
  181. Buffer,
  182. Size
  183. );
  184. if (!NT_SUCCESS(status)) {
  185. printf("status: 0x%08X\n", status);
  186. free(Buffer);
  187. break;
  188. }
  189. printf(
  190. "Retrieved %d bytes\n",
  191. Size = (ULONG)IoStatusBlock.Information
  192. );
  193. DumpBuffer(Buffer, Size);
  194. free(Buffer);
  195. break;
  196. }
  197. case 2: {
  198. IP_NAT_INTERFACE_STATISTICS InterfaceStats;
  199. status = NtDeviceIoControlFile(
  200. NatHandle,
  201. NULL,
  202. NULL,
  203. NULL,
  204. &IoStatusBlock,
  205. IOCTL_IP_NAT_GET_INTERFACE_STATISTICS,
  206. (PVOID)&InterfaceIndex,
  207. sizeof(InterfaceIndex),
  208. (PVOID)&InterfaceStats,
  209. sizeof(InterfaceStats)
  210. );
  211. if (!NT_SUCCESS(status)) {
  212. printf("status: 0x%08X\n", status);
  213. break;
  214. }
  215. printf(
  216. "Total Mappings: %d\n", InterfaceStats.TotalMappings);
  217. printf(
  218. "Inbound Mappings: %d\n", InterfaceStats.InboundMappings);
  219. printf(
  220. "Packets Forward: %d\n",
  221. InterfaceStats.PacketsForward);
  222. printf(
  223. "Packets Reverse: %d\n",
  224. InterfaceStats.PacketsReverse);
  225. printf(
  226. "Rejects Forward: %d\n",
  227. InterfaceStats.RejectsForward);
  228. printf(
  229. "Rejects Reverse: %d\n",
  230. InterfaceStats.RejectsReverse);
  231. break;
  232. }
  233. case 3: {
  234. UCHAR Buffer[128];
  235. PIP_NAT_ENUMERATE_SESSION_MAPPINGS Enum =
  236. (PIP_NAT_ENUMERATE_SESSION_MAPPINGS)Buffer;
  237. ULONG i;
  238. Enum->Index = InterfaceIndex;
  239. Enum->EnumerateContext[0] = 0;
  240. #if 0
  241. printf(
  242. "%3s %4s %15s/%-5s %15s/%-5s %15s/%-5s %-5s\n"
  243. "DIR", "PROT",
  244. "PrivateAddr", "Port",
  245. "PublicAddr", "Port",
  246. "RemoteAddr", "Port",
  247. "Idle"
  248. );
  249. #endif
  250. do {
  251. status = NtDeviceIoControlFile(
  252. NatHandle,
  253. NULL,
  254. NULL,
  255. NULL,
  256. &IoStatusBlock,
  257. IOCTL_IP_NAT_GET_MAPPING_TABLE,
  258. (PVOID)Enum,
  259. FIELD_OFFSET(
  260. IP_NAT_ENUMERATE_SESSION_MAPPINGS,
  261. EnumerateTable),
  262. (PVOID)Enum,
  263. sizeof(Buffer)
  264. );
  265. if (!NT_SUCCESS(status)) {
  266. printf("status: 0x%08X\n", status);
  267. break;
  268. }
  269. for (i = 0; i < Enum->EnumerateCount; i++) {
  270. DisplayMapping(&Enum->EnumerateTable[i]);
  271. }
  272. } while(Enum->EnumerateContext[0]);
  273. break;
  274. }
  275. }
  276. }
  277. #endif
  278. if (NatHandle) { NtClose(NatHandle); }
  279. NtClose(IpHandle);
  280. return STATUS_SUCCESS;
  281. } // main
  282. VOID
  283. DisplayMapping(
  284. PIP_NAT_SESSION_MAPPING Mapping
  285. )
  286. {
  287. CHAR PrivateAddress[16];
  288. CHAR PublicAddress[16];
  289. CHAR RemoteAddress[16];
  290. strcpy(PrivateAddress, INET_NTOA(Mapping->PrivateAddress));
  291. strcpy(PublicAddress, INET_NTOA(Mapping->PublicAddress));
  292. strcpy(RemoteAddress, INET_NTOA(Mapping->RemoteAddress));
  293. printf(
  294. MAPPING_FORMAT,
  295. Mapping->Direction == NatInboundDirection ? "IN" : "OUT",
  296. Mapping->Protocol == NAT_PROTOCOL_TCP ? "TCP" : "UDP",
  297. PrivateAddress, ntohs(Mapping->PrivatePort),
  298. PublicAddress, ntohs(Mapping->PublicPort),
  299. RemoteAddress, ntohs(Mapping->RemotePort),
  300. Mapping->IdleTime
  301. );
  302. }
  303. VOID
  304. DumpBuffer(
  305. PUCHAR Buffer,
  306. ULONG Size
  307. )
  308. {
  309. int i;
  310. PULONG Next;
  311. for (i = 0, Next = (PULONG)Buffer; Next < (PULONG)(Buffer + Size); Next++, i++) {
  312. printf("0x%08X ", *Next);
  313. if ((i % 4) == 3) { printf("\n"); }
  314. }
  315. if ((i % 4) != 0) { printf("\n"); }
  316. }
  317. typedef HANDLE
  318. (WINAPI *PCREATE_CAPTURE)(
  319. PVOID A1,
  320. PVOID A2,
  321. PVOID A3
  322. );
  323. typedef UINT
  324. (WINAPI *PDESTROY_CAPTURE)(
  325. HANDLE CaptureHandle
  326. );
  327. typedef ULONG
  328. (WINAPI *PLOAD_CAPTURE)(
  329. HANDLE CaptureHandle,
  330. PCHAR FileName
  331. );
  332. typedef ULONG
  333. (WINAPI *PGET_CAPTURE_TOTAL_FRAMES)(
  334. HANDLE CaptureHandle
  335. );
  336. typedef HANDLE
  337. (WINAPI *PGET_FRAME)(
  338. HANDLE CaptureHandle,
  339. ULONG FrameNumber
  340. );
  341. typedef PUCHAR
  342. (WINAPI *PLOCK_FRAME)(
  343. HANDLE FrameHandle
  344. );
  345. typedef ULONG
  346. (WINAPI *PUNLOCK_FRAME)(
  347. HANDLE FrameHandle
  348. );
  349. typedef ULONG
  350. (WINAPI *PGET_FRAME_MAC_TYPE)(
  351. HANDLE FrameHandle
  352. );
  353. typedef ULONG
  354. (WINAPI *PGET_FRAME_MAC_HEADER_LENGTH)(
  355. HANDLE FrameHandle
  356. );
  357. NTSTATUS
  358. CreateLocalInterface(
  359. ULONG Address,
  360. ULONG Mask
  361. )
  362. {
  363. UCHAR Buffer[1024];
  364. ULONG i;
  365. ULONG IfIndex;
  366. PMIB_IFTABLE IfTable = NULL;
  367. ULONG IfSize;
  368. IO_STATUS_BLOCK IoStatusBlock;
  369. PMIB_IPADDRTABLE IpAddrTable = NULL;
  370. ULONG IpAddrSize;
  371. ULONG j;
  372. NTSTATUS status;
  373. //
  374. // Retrieve a table of the local interfaces
  375. //
  376. IfSize = 0;
  377. status = GetIfTable(
  378. NULL,
  379. &IfSize,
  380. FALSE
  381. );
  382. if (status != ERROR_INSUFFICIENT_BUFFER) { return STATUS_UNSUCCESSFUL; }
  383. IfTable = (PMIB_IFTABLE)malloc(IfSize);
  384. if (!IfTable) { return STATUS_NO_MEMORY; }
  385. memset(IfTable, 0, IfSize);
  386. if (!Address) {
  387. //
  388. // Retrieve a table of the local addresses
  389. //
  390. IpAddrSize = 0;
  391. status = GetIpAddrTable(
  392. NULL,
  393. &IpAddrSize,
  394. FALSE
  395. );
  396. if (status != ERROR_INSUFFICIENT_BUFFER) {
  397. free(IfTable); return STATUS_UNSUCCESSFUL;
  398. }
  399. IpAddrTable = (PMIB_IPADDRTABLE)malloc(IpAddrSize);
  400. if (!IpAddrTable) {
  401. free(IfTable); return STATUS_NO_MEMORY;
  402. }
  403. }
  404. do {
  405. status = GetIfTable(
  406. IfTable,
  407. &IfSize,
  408. FALSE
  409. );
  410. if (status != NO_ERROR) { status = STATUS_UNSUCCESSFUL; break; }
  411. if (Address) {
  412. for (i = 0; i < IfTable->dwNumEntries; i++) {
  413. printf(
  414. "%d. %s [%d]\n", i, IfTable->table[i].bDescr,
  415. IfTable->table[i].dwIndex
  416. );
  417. }
  418. printf("\nEnter interface index: ");
  419. scanf("%d", &IfIndex);
  420. }
  421. else {
  422. status = GetIpAddrTable(
  423. IpAddrTable,
  424. &IpAddrSize,
  425. FALSE
  426. );
  427. if (status != NO_ERROR) { status = STATUS_UNSUCCESSFUL; break; }
  428. //
  429. // Display the interfaces
  430. //
  431. for (i = 0; i < IfTable->dwNumEntries; i++) {
  432. printf("%d. %s ", i, IfTable->table[i].bDescr);
  433. IfTable->table[i].dwSpeed = (ULONG)-1;
  434. for (j = 0; j < IpAddrTable->dwNumEntries; j++) {
  435. if (IpAddrTable->table[j].dwIndex ==
  436. IfTable->table[i].dwIndex){
  437. printf("[%s]", INET_NTOA(IpAddrTable->table[j].dwAddr));
  438. IfTable->table[i].dwSpeed = j;
  439. break;
  440. }
  441. }
  442. printf("\n");
  443. }
  444. do {
  445. printf("\nEnter boundary interface (0-%d): ", i-1);
  446. scanf("%d", &i);
  447. } while (
  448. i >= IfTable->dwNumEntries ||
  449. IfTable->table[i].dwSpeed == (ULONG)-1
  450. );
  451. Address = IpAddrTable->table[IfTable->table[i].dwSpeed].dwAddr;
  452. Mask = IpAddrTable->table[IfTable->table[i].dwSpeed].dwMask;
  453. IfIndex = IfTable->table[i].dwIndex;
  454. }
  455. //
  456. // Set the selected interface up as a boundary interface
  457. //
  458. IP_NAT_INTERFACE_INFO IfInfo;
  459. ZeroMemory(&IfInfo, sizeof(IfInfo));
  460. IfInfo.Index = IfIndex;
  461. IfInfo.Header.Version = IP_NAT_VERSION;
  462. IfInfo.Header.Size = FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry);
  463. IfInfo.Header.TocEntriesCount = 0;
  464. IfInfo.Flags =
  465. IP_NAT_INTERFACE_FLAGS_BOUNDARY|IP_NAT_INTERFACE_FLAGS_NAPT;
  466. status =
  467. NtDeviceIoControlFile(
  468. NatHandle,
  469. NULL,
  470. NULL,
  471. NULL,
  472. &IoStatusBlock,
  473. IOCTL_IP_NAT_SET_INTERFACE_INFO,
  474. (PVOID)&IfInfo,
  475. sizeof(IfInfo),
  476. NULL,
  477. 0
  478. );
  479. if (!NT_SUCCESS(status)) {
  480. printf("Error 0x%08X configuring interface.\n", status); break;
  481. }
  482. InterfaceIndex = IfIndex;
  483. } while(FALSE);
  484. if (IpAddrTable) { free(IpAddrTable); }
  485. if (IfTable) { free(IfTable); }
  486. return status;
  487. }