/*++ Copyright (c) 1997 Microsoft Corporation Module Name: natc.c Abstract: This module contains code for testing the functionality of the NAT. Author: Abolade Gbadegesin (t-abolag) 15-July-1997 Revision History: --*/ extern "C" { #include #include #include #include #include #include #include #include #include #include #include #include #include #undef ERROR #include "debug.h" #include "prot.h" } #define INET_NTOA(a) inet_ntoa(*(struct in_addr*)&(a)) #define MAPPING_FORMAT "%3s %4s %15s/%-5d %15s/%-5d %15s/%-5d %-5d\n" #define IF_COUNT 3 #define MAKE_ADDRESS(a,b,c,d) \ ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24)) #define NETORDER_PORT(a) \ ((((a) & 0xFF00) >> 8) | (((a) & 0x00FF) << 8)) ULONG InterfaceIndex; HANDLE IpHandle = NULL; HANDLE NatHandle = NULL; // // FORWARD DECLARATIONS // NTSTATUS CreateLocalInterface( ULONG Address, ULONG Mask ); VOID DisplayMapping( PIP_NAT_SESSION_MAPPING Mapping ); VOID DumpBuffer( PUCHAR Buffer, ULONG Size ); LONG __cdecl main( LONG argc, CHAR* argv[] ) /*++ --*/ { UCHAR Buffer[256]; UNICODE_STRING DeviceString; PRTR_INFO_BLOCK_HEADER Header; LONG i; LONG j; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; ULONG Offset; NTSTATUS status; ULONG TocCount; ULONG TocEntry; // // Open the IP driver // RtlInitUnicodeString(&DeviceString, DD_IP_DEVICE_NAME); InitializeObjectAttributes( &ObjectAttributes, &DeviceString, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtCreateFile( &IpHandle, SYNCHRONIZE|FILE_READ_DATA|FILE_WRITE_DATA, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0 ); if (!NT_SUCCESS(status)) { printf("Error 0x%08X opening IP driver.\n", status); return status; } if (argc != 3) { // // Open the NAT driver // RtlInitUnicodeString(&DeviceString, DD_IP_NAT_DEVICE_NAME); InitializeObjectAttributes( &ObjectAttributes, &DeviceString, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtCreateFile( &NatHandle, SYNCHRONIZE|FILE_READ_DATA|FILE_WRITE_DATA, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0 ); if (!NT_SUCCESS(status)) { printf("Error 0x%08X opening NAT driver.\n", status); NtClose(IpHandle); return status; } } if (argc >= 2 && lstrcmpi(argv[1], "-x") == 0) { CreateLocalInterface( argc == 4 ? inet_addr(argv[2]) : 0, argc == 4 ? inet_addr(argv[3]) : 0 ); } #if DBG for (;;) { ULONG Option = 0; printf("0. Quit\n"); printf("1. Get Interface Info\n"); printf("2. Get Interface Statistics\n"); printf("3. Enumerate Session Mappings\n"); scanf("%d", &Option); if (!Option) { break; } if (!InterfaceIndex) { printf("Enter interface index: "); scanf("%d", &InterfaceIndex); } switch(Option) { case 1: { PUCHAR Buffer; IP_NAT_INTERFACE_INFO InterfaceInfo; ULONG Size; InterfaceInfo.Index = InterfaceIndex; status = NtDeviceIoControlFile( NatHandle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_IP_NAT_GET_INTERFACE_INFO, (PVOID)&InterfaceInfo, sizeof(InterfaceInfo), NULL, 0 ); if (!NT_SUCCESS(status)) { printf("status: 0x%08X\n", status); break; } printf( "Allocating %d bytes\n", Size = (ULONG)IoStatusBlock.Information ); Buffer = (PUCHAR)malloc(Size); status = NtDeviceIoControlFile( NatHandle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_IP_NAT_GET_INTERFACE_INFO, (PVOID)&InterfaceInfo, sizeof(InterfaceInfo), Buffer, Size ); if (!NT_SUCCESS(status)) { printf("status: 0x%08X\n", status); free(Buffer); break; } printf( "Retrieved %d bytes\n", Size = (ULONG)IoStatusBlock.Information ); DumpBuffer(Buffer, Size); free(Buffer); break; } case 2: { IP_NAT_INTERFACE_STATISTICS InterfaceStats; status = NtDeviceIoControlFile( NatHandle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_IP_NAT_GET_INTERFACE_STATISTICS, (PVOID)&InterfaceIndex, sizeof(InterfaceIndex), (PVOID)&InterfaceStats, sizeof(InterfaceStats) ); if (!NT_SUCCESS(status)) { printf("status: 0x%08X\n", status); break; } printf( "Total Mappings: %d\n", InterfaceStats.TotalMappings); printf( "Inbound Mappings: %d\n", InterfaceStats.InboundMappings); printf( "Packets Forward: %d\n", InterfaceStats.PacketsForward); printf( "Packets Reverse: %d\n", InterfaceStats.PacketsReverse); printf( "Rejects Forward: %d\n", InterfaceStats.RejectsForward); printf( "Rejects Reverse: %d\n", InterfaceStats.RejectsReverse); break; } case 3: { UCHAR Buffer[128]; PIP_NAT_ENUMERATE_SESSION_MAPPINGS Enum = (PIP_NAT_ENUMERATE_SESSION_MAPPINGS)Buffer; ULONG i; Enum->Index = InterfaceIndex; Enum->EnumerateContext[0] = 0; #if 0 printf( "%3s %4s %15s/%-5s %15s/%-5s %15s/%-5s %-5s\n" "DIR", "PROT", "PrivateAddr", "Port", "PublicAddr", "Port", "RemoteAddr", "Port", "Idle" ); #endif do { status = NtDeviceIoControlFile( NatHandle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_IP_NAT_GET_MAPPING_TABLE, (PVOID)Enum, FIELD_OFFSET( IP_NAT_ENUMERATE_SESSION_MAPPINGS, EnumerateTable), (PVOID)Enum, sizeof(Buffer) ); if (!NT_SUCCESS(status)) { printf("status: 0x%08X\n", status); break; } for (i = 0; i < Enum->EnumerateCount; i++) { DisplayMapping(&Enum->EnumerateTable[i]); } } while(Enum->EnumerateContext[0]); break; } } } #endif if (NatHandle) { NtClose(NatHandle); } NtClose(IpHandle); return STATUS_SUCCESS; } // main VOID DisplayMapping( PIP_NAT_SESSION_MAPPING Mapping ) { CHAR PrivateAddress[16]; CHAR PublicAddress[16]; CHAR RemoteAddress[16]; strcpy(PrivateAddress, INET_NTOA(Mapping->PrivateAddress)); strcpy(PublicAddress, INET_NTOA(Mapping->PublicAddress)); strcpy(RemoteAddress, INET_NTOA(Mapping->RemoteAddress)); printf( MAPPING_FORMAT, Mapping->Direction == NatInboundDirection ? "IN" : "OUT", Mapping->Protocol == NAT_PROTOCOL_TCP ? "TCP" : "UDP", PrivateAddress, ntohs(Mapping->PrivatePort), PublicAddress, ntohs(Mapping->PublicPort), RemoteAddress, ntohs(Mapping->RemotePort), Mapping->IdleTime ); } VOID DumpBuffer( PUCHAR Buffer, ULONG Size ) { int i; PULONG Next; for (i = 0, Next = (PULONG)Buffer; Next < (PULONG)(Buffer + Size); Next++, i++) { printf("0x%08X ", *Next); if ((i % 4) == 3) { printf("\n"); } } if ((i % 4) != 0) { printf("\n"); } } typedef HANDLE (WINAPI *PCREATE_CAPTURE)( PVOID A1, PVOID A2, PVOID A3 ); typedef UINT (WINAPI *PDESTROY_CAPTURE)( HANDLE CaptureHandle ); typedef ULONG (WINAPI *PLOAD_CAPTURE)( HANDLE CaptureHandle, PCHAR FileName ); typedef ULONG (WINAPI *PGET_CAPTURE_TOTAL_FRAMES)( HANDLE CaptureHandle ); typedef HANDLE (WINAPI *PGET_FRAME)( HANDLE CaptureHandle, ULONG FrameNumber ); typedef PUCHAR (WINAPI *PLOCK_FRAME)( HANDLE FrameHandle ); typedef ULONG (WINAPI *PUNLOCK_FRAME)( HANDLE FrameHandle ); typedef ULONG (WINAPI *PGET_FRAME_MAC_TYPE)( HANDLE FrameHandle ); typedef ULONG (WINAPI *PGET_FRAME_MAC_HEADER_LENGTH)( HANDLE FrameHandle ); NTSTATUS CreateLocalInterface( ULONG Address, ULONG Mask ) { UCHAR Buffer[1024]; ULONG i; ULONG IfIndex; PMIB_IFTABLE IfTable = NULL; ULONG IfSize; IO_STATUS_BLOCK IoStatusBlock; PMIB_IPADDRTABLE IpAddrTable = NULL; ULONG IpAddrSize; ULONG j; NTSTATUS status; // // Retrieve a table of the local interfaces // IfSize = 0; status = GetIfTable( NULL, &IfSize, FALSE ); if (status != ERROR_INSUFFICIENT_BUFFER) { return STATUS_UNSUCCESSFUL; } IfTable = (PMIB_IFTABLE)malloc(IfSize); if (!IfTable) { return STATUS_NO_MEMORY; } memset(IfTable, 0, IfSize); if (!Address) { // // Retrieve a table of the local addresses // IpAddrSize = 0; status = GetIpAddrTable( NULL, &IpAddrSize, FALSE ); if (status != ERROR_INSUFFICIENT_BUFFER) { free(IfTable); return STATUS_UNSUCCESSFUL; } IpAddrTable = (PMIB_IPADDRTABLE)malloc(IpAddrSize); if (!IpAddrTable) { free(IfTable); return STATUS_NO_MEMORY; } } do { status = GetIfTable( IfTable, &IfSize, FALSE ); if (status != NO_ERROR) { status = STATUS_UNSUCCESSFUL; break; } if (Address) { for (i = 0; i < IfTable->dwNumEntries; i++) { printf( "%d. %s [%d]\n", i, IfTable->table[i].bDescr, IfTable->table[i].dwIndex ); } printf("\nEnter interface index: "); scanf("%d", &IfIndex); } else { status = GetIpAddrTable( IpAddrTable, &IpAddrSize, FALSE ); if (status != NO_ERROR) { status = STATUS_UNSUCCESSFUL; break; } // // Display the interfaces // for (i = 0; i < IfTable->dwNumEntries; i++) { printf("%d. %s ", i, IfTable->table[i].bDescr); IfTable->table[i].dwSpeed = (ULONG)-1; for (j = 0; j < IpAddrTable->dwNumEntries; j++) { if (IpAddrTable->table[j].dwIndex == IfTable->table[i].dwIndex){ printf("[%s]", INET_NTOA(IpAddrTable->table[j].dwAddr)); IfTable->table[i].dwSpeed = j; break; } } printf("\n"); } do { printf("\nEnter boundary interface (0-%d): ", i-1); scanf("%d", &i); } while ( i >= IfTable->dwNumEntries || IfTable->table[i].dwSpeed == (ULONG)-1 ); Address = IpAddrTable->table[IfTable->table[i].dwSpeed].dwAddr; Mask = IpAddrTable->table[IfTable->table[i].dwSpeed].dwMask; IfIndex = IfTable->table[i].dwIndex; } // // Set the selected interface up as a boundary interface // IP_NAT_INTERFACE_INFO IfInfo; ZeroMemory(&IfInfo, sizeof(IfInfo)); IfInfo.Index = IfIndex; IfInfo.Header.Version = IP_NAT_VERSION; IfInfo.Header.Size = FIELD_OFFSET(RTR_INFO_BLOCK_HEADER, TocEntry); IfInfo.Header.TocEntriesCount = 0; IfInfo.Flags = IP_NAT_INTERFACE_FLAGS_BOUNDARY|IP_NAT_INTERFACE_FLAGS_NAPT; status = NtDeviceIoControlFile( NatHandle, NULL, NULL, NULL, &IoStatusBlock, IOCTL_IP_NAT_SET_INTERFACE_INFO, (PVOID)&IfInfo, sizeof(IfInfo), NULL, 0 ); if (!NT_SUCCESS(status)) { printf("Error 0x%08X configuring interface.\n", status); break; } InterfaceIndex = IfIndex; } while(FALSE); if (IpAddrTable) { free(IpAddrTable); } if (IfTable) { free(IfTable); } return status; }