1423 lines
46 KiB
C++
1423 lines
46 KiB
C++
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
#include <nt.h>
|
|||
|
#include <ntrtl.h>
|
|||
|
#include <nturtl.h>
|
|||
|
#include <mswsock.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <conio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <ipnatapi.h>
|
|||
|
|
|||
|
HANDLE Event;
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
ReadCompletionRoutine(
|
|||
|
ULONG ErrorCode,
|
|||
|
ULONG BytesTransferred,
|
|||
|
PNH_BUFFER Bufferp
|
|||
|
)
|
|||
|
{
|
|||
|
printf(
|
|||
|
"ReadCompletionRoutine: e=%u, b=%u, '%s'\n",
|
|||
|
ErrorCode, BytesTransferred, Bufferp->Buffer
|
|||
|
);
|
|||
|
NhReleaseBuffer(Bufferp);
|
|||
|
SetEvent(Event);
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
WriteCompletionRoutine(
|
|||
|
ULONG ErrorCode,
|
|||
|
ULONG BytesTransferred,
|
|||
|
PNH_BUFFER Bufferp
|
|||
|
)
|
|||
|
{
|
|||
|
printf(
|
|||
|
"WriteCompletionRoutine: e=%u, b=%u, %08x\n",
|
|||
|
ErrorCode, BytesTransferred, Bufferp
|
|||
|
);
|
|||
|
NhReleaseBuffer(Bufferp);
|
|||
|
SetEvent(Event);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
AcceptCompletionRoutine(
|
|||
|
ULONG ErrorCode,
|
|||
|
ULONG BytesTransferred,
|
|||
|
PNH_BUFFER Bufferp
|
|||
|
)
|
|||
|
{
|
|||
|
SOCKET AcceptedSocket;
|
|||
|
SOCKET ListeningSocket;
|
|||
|
printf(
|
|||
|
"AcceptCompletionRoutine: e=%u, b=%u\n",
|
|||
|
ErrorCode, BytesTransferred
|
|||
|
);
|
|||
|
ListeningSocket = (SOCKET)Bufferp->Context;
|
|||
|
AcceptedSocket = (SOCKET)Bufferp->Context2;
|
|||
|
ErrorCode =
|
|||
|
setsockopt(
|
|||
|
AcceptedSocket,
|
|||
|
SOL_SOCKET,
|
|||
|
SO_UPDATE_ACCEPT_CONTEXT,
|
|||
|
(PCHAR)&ListeningSocket,
|
|||
|
sizeof(ListeningSocket)
|
|||
|
);
|
|||
|
if (ErrorCode == SOCKET_ERROR) {
|
|||
|
printf("error %d updating accept context\n", WSAGetLastError());
|
|||
|
NhReleaseBuffer(Bufferp);
|
|||
|
SetEvent(Event);
|
|||
|
} else {
|
|||
|
ErrorCode =
|
|||
|
NhReadStreamSocket(
|
|||
|
NULL,
|
|||
|
AcceptedSocket,
|
|||
|
Bufferp,
|
|||
|
NH_BUFFER_SIZE,
|
|||
|
0,
|
|||
|
ReadCompletionRoutine,
|
|||
|
NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
if (ErrorCode != NO_ERROR) {
|
|||
|
printf("error %d reading from accepted socket\n", ErrorCode);
|
|||
|
NhReleaseBuffer(Bufferp);
|
|||
|
SetEvent(Event);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
TestApiCompletionRoutine(
|
|||
|
HANDLE RedirectHandle,
|
|||
|
BOOLEAN Cancelled,
|
|||
|
PVOID CompletionContext
|
|||
|
)
|
|||
|
{
|
|||
|
NAT_BYTE_COUNT_REDIRECT_INFORMATION ByteCount;
|
|||
|
ULONG Error;
|
|||
|
ULONG Length = sizeof(ByteCount);
|
|||
|
printf("TestApiCompletionRoutine=%x,%d\n", RedirectHandle, Cancelled);
|
|||
|
Error =
|
|||
|
NatQueryInformationRedirectHandle(
|
|||
|
RedirectHandle,
|
|||
|
&ByteCount,
|
|||
|
&Length,
|
|||
|
NatByteCountRedirectInformation
|
|||
|
);
|
|||
|
printf(
|
|||
|
"TestApiCompletionRoutine=%d,bc={%I64d,%I64d},l=%d\n",
|
|||
|
Error, ByteCount.BytesForward, ByteCount.BytesReverse, Length
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Error;
|
|||
|
HANDLE TranslatorHandle;
|
|||
|
|
|||
|
Error = NatInitializeTranslator(&TranslatorHandle);
|
|||
|
if (Error) {
|
|||
|
printf("NatInitializeTranslator=%d\n", Error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
|
|||
|
Error =
|
|||
|
NatCreateRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
0,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
htons((USHORT)atol(argv[8])),
|
|||
|
inet_addr(argv[9]),
|
|||
|
htons((USHORT)atol(argv[10])),
|
|||
|
TestApiCompletionRoutine,
|
|||
|
NULL,
|
|||
|
Event
|
|||
|
);
|
|||
|
printf("NatCreateRedirect=%d\n", Error);
|
|||
|
if (!Error) {
|
|||
|
for (;;) {
|
|||
|
Error = WaitForSingleObjectEx(Event, 1000, TRUE);
|
|||
|
printf("WaitForSingleObjectEx=%d\n", Error);
|
|||
|
if (Error == WAIT_IO_COMPLETION) {
|
|||
|
break;
|
|||
|
} else if (Error == WAIT_OBJECT_0) {
|
|||
|
NAT_SOURCE_MAPPING_REDIRECT_INFORMATION SourceMapping;
|
|||
|
ULONG Length = sizeof(SourceMapping);
|
|||
|
CHAR src[32], newsrc[32];
|
|||
|
NatQueryInformationRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
htons((USHORT)atol(argv[8])),
|
|||
|
inet_addr(argv[9]),
|
|||
|
htons((USHORT)atol(argv[10])),
|
|||
|
&SourceMapping,
|
|||
|
&Length,
|
|||
|
NatSourceMappingRedirectInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
src,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.SourceAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newsrc,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.NewSourceAddress)
|
|||
|
);
|
|||
|
printf("redirect activated: %s->%s\n", src, newsrc);
|
|||
|
}
|
|||
|
if (_kbhit()) {
|
|||
|
switch(getchar()) {
|
|||
|
case 'q': { break; }
|
|||
|
case 's': {
|
|||
|
NAT_BYTE_COUNT_REDIRECT_INFORMATION ByteCount;
|
|||
|
ULONG Length = sizeof(ByteCount);
|
|||
|
NatQueryInformationRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
htons((USHORT)atol(argv[8])),
|
|||
|
inet_addr(argv[9]),
|
|||
|
htons((USHORT)atol(argv[10])),
|
|||
|
&ByteCount,
|
|||
|
&Length,
|
|||
|
NatByteCountRedirectInformation
|
|||
|
);
|
|||
|
printf(
|
|||
|
"NatQueryInformationRedirect=%d,{%I64d,%I64d}\n",
|
|||
|
Error,
|
|||
|
ByteCount.BytesForward,
|
|||
|
ByteCount.BytesReverse
|
|||
|
);
|
|||
|
// fall-through
|
|||
|
}
|
|||
|
default: continue;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (Error != WAIT_IO_COMPLETION) {
|
|||
|
Error =
|
|||
|
NatCancelRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
htons((USHORT)atol(argv[8])),
|
|||
|
inet_addr(argv[9]),
|
|||
|
htons((USHORT)atol(argv[10]))
|
|||
|
);
|
|||
|
printf("NatCancelRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf("NatShutdownTranslator...");
|
|||
|
NatShutdownTranslator(TranslatorHandle);
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestPartialRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Error;
|
|||
|
HANDLE TranslatorHandle;
|
|||
|
|
|||
|
Error = NatInitializeTranslator(&TranslatorHandle);
|
|||
|
if (Error) {
|
|||
|
printf("NatInitializeTranslator=%d\n", Error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
|
|||
|
Error =
|
|||
|
NatCreatePartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
0,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
TestApiCompletionRoutine,
|
|||
|
NULL,
|
|||
|
Event
|
|||
|
);
|
|||
|
printf("NatCreatePartialRedirect=%d\n", Error);
|
|||
|
if (!Error) {
|
|||
|
for (;;) {
|
|||
|
Error = WaitForSingleObjectEx(Event, 1000, TRUE);
|
|||
|
printf("WaitForSingleObjectEx=%d\n", Error);
|
|||
|
if (Error == WAIT_IO_COMPLETION) {
|
|||
|
break;
|
|||
|
} else if (Error == WAIT_OBJECT_0) {
|
|||
|
NAT_SOURCE_MAPPING_REDIRECT_INFORMATION SourceMapping;
|
|||
|
ULONG Length = sizeof(SourceMapping);
|
|||
|
CHAR src[32], newsrc[32];
|
|||
|
NatQueryInformationPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
&SourceMapping,
|
|||
|
&Length,
|
|||
|
NatSourceMappingRedirectInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
src,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.SourceAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newsrc,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.NewSourceAddress)
|
|||
|
);
|
|||
|
printf("redirect activated: %s->%s\n", src, newsrc);
|
|||
|
}
|
|||
|
if (_kbhit()) {
|
|||
|
switch(getchar()) {
|
|||
|
case 'q': { break; }
|
|||
|
case 's': {
|
|||
|
NAT_BYTE_COUNT_REDIRECT_INFORMATION ByteCount;
|
|||
|
ULONG Length = sizeof(ByteCount);
|
|||
|
NatQueryInformationPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
&ByteCount,
|
|||
|
&Length,
|
|||
|
NatByteCountRedirectInformation
|
|||
|
);
|
|||
|
printf(
|
|||
|
"NatQueryInformationPartialRedirect="
|
|||
|
"%d,{%I64d,%I64d}\n",
|
|||
|
Error,
|
|||
|
ByteCount.BytesForward,
|
|||
|
ByteCount.BytesReverse
|
|||
|
);
|
|||
|
// fall-through
|
|||
|
}
|
|||
|
default: continue;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (Error != WAIT_IO_COMPLETION) {
|
|||
|
Error =
|
|||
|
NatCancelPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6]))
|
|||
|
);
|
|||
|
printf("NatCancelPartialRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf("NatShutdownTranslator...");
|
|||
|
NatShutdownTranslator(TranslatorHandle);
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestPortRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Error;
|
|||
|
HANDLE TranslatorHandle;
|
|||
|
|
|||
|
Error = NatInitializeTranslator(&TranslatorHandle);
|
|||
|
if (Error) {
|
|||
|
printf("NatInitializeTranslator=%d\n", Error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
|
|||
|
Error =
|
|||
|
NatCreatePortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
0,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
TestApiCompletionRoutine,
|
|||
|
NULL,
|
|||
|
Event
|
|||
|
);
|
|||
|
printf("NatCreatePortRedirect=%d\n", Error);
|
|||
|
if (!Error) {
|
|||
|
for (;;) {
|
|||
|
Error = WaitForSingleObjectEx(Event, 1000, TRUE);
|
|||
|
printf("WaitForSingleObjectEx=%d\n", Error);
|
|||
|
if (Error == WAIT_IO_COMPLETION) {
|
|||
|
break;
|
|||
|
} else if (Error == WAIT_OBJECT_0) {
|
|||
|
NAT_SOURCE_MAPPING_REDIRECT_INFORMATION SourceMapping;
|
|||
|
NAT_DESTINATION_MAPPING_REDIRECT_INFORMATION DestinationMapping;
|
|||
|
ULONG Length;
|
|||
|
CHAR src[32], newsrc[32], dst[32], newdst[32];
|
|||
|
Length = sizeof(SourceMapping);
|
|||
|
NatQueryInformationPortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
&SourceMapping,
|
|||
|
&Length,
|
|||
|
NatSourceMappingRedirectInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
src,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.SourceAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newsrc,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.NewSourceAddress)
|
|||
|
);
|
|||
|
Length = sizeof(DestinationMapping);
|
|||
|
NatQueryInformationPortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
&DestinationMapping,
|
|||
|
&Length,
|
|||
|
NatDestinationMappingRedirectInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
dst,
|
|||
|
inet_ntoa(*(PIN_ADDR)&DestinationMapping.DestinationAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newdst,
|
|||
|
inet_ntoa(*(PIN_ADDR)&DestinationMapping.NewDestinationAddress)
|
|||
|
);
|
|||
|
printf("redirect activated: %s:%s->%s:%s\n", src, dst, newsrc, newdst);
|
|||
|
}
|
|||
|
if (_kbhit()) {
|
|||
|
switch(getchar()) {
|
|||
|
case 'q': { break; }
|
|||
|
case 's': {
|
|||
|
NAT_BYTE_COUNT_REDIRECT_INFORMATION ByteCount;
|
|||
|
ULONG Length = sizeof(ByteCount);
|
|||
|
NatQueryInformationPortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
&ByteCount,
|
|||
|
&Length,
|
|||
|
NatByteCountRedirectInformation
|
|||
|
);
|
|||
|
printf(
|
|||
|
"NatQueryInformationPortRedirect="
|
|||
|
"%d,{%I64d,%I64d}\n",
|
|||
|
Error,
|
|||
|
ByteCount.BytesForward,
|
|||
|
ByteCount.BytesReverse
|
|||
|
);
|
|||
|
// fall-through
|
|||
|
}
|
|||
|
default: continue;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (Error != WAIT_IO_COMPLETION) {
|
|||
|
Error =
|
|||
|
NatCancelPortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5]))
|
|||
|
);
|
|||
|
printf("NatCancelPortRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf("NatShutdownTranslator...");
|
|||
|
NatShutdownTranslator(TranslatorHandle);
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestReceiveOnlyPortRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Error;
|
|||
|
HANDLE TranslatorHandle;
|
|||
|
|
|||
|
Error = NatInitializeTranslator(&TranslatorHandle);
|
|||
|
if (Error) {
|
|||
|
printf("NatInitializeTranslator=%d\n", Error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
|
|||
|
Error =
|
|||
|
NatCreatePortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
NatRedirectFlagReceiveOnly,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
TestApiCompletionRoutine,
|
|||
|
NULL,
|
|||
|
Event
|
|||
|
);
|
|||
|
printf("NatCreatePortRedirect=%d\n", Error);
|
|||
|
if (!Error) {
|
|||
|
for (;;) {
|
|||
|
Error = WaitForSingleObjectEx(Event, 1000, TRUE);
|
|||
|
printf("WaitForSingleObjectEx=%d\n", Error);
|
|||
|
if (Error == WAIT_IO_COMPLETION) {
|
|||
|
break;
|
|||
|
} else if (Error == WAIT_OBJECT_0) {
|
|||
|
NAT_SOURCE_MAPPING_REDIRECT_INFORMATION SourceMapping;
|
|||
|
NAT_DESTINATION_MAPPING_REDIRECT_INFORMATION DestinationMapping;
|
|||
|
ULONG Length;
|
|||
|
CHAR src[32], newsrc[32], dst[32], newdst[32];
|
|||
|
Length = sizeof(SourceMapping);
|
|||
|
NatQueryInformationPortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
&SourceMapping,
|
|||
|
&Length,
|
|||
|
NatSourceMappingRedirectInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
src,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.SourceAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newsrc,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.NewSourceAddress)
|
|||
|
);
|
|||
|
Length = sizeof(DestinationMapping);
|
|||
|
NatQueryInformationPortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
&DestinationMapping,
|
|||
|
&Length,
|
|||
|
NatDestinationMappingRedirectInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
dst,
|
|||
|
inet_ntoa(*(PIN_ADDR)&DestinationMapping.DestinationAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newdst,
|
|||
|
inet_ntoa(*(PIN_ADDR)&DestinationMapping.NewDestinationAddress)
|
|||
|
);
|
|||
|
printf("redirect activated: %s:%s->%s:%s\n", src, dst, newsrc, newdst);
|
|||
|
}
|
|||
|
if (_kbhit()) {
|
|||
|
switch(getchar()) {
|
|||
|
case 'q': { break; }
|
|||
|
case 's': {
|
|||
|
NAT_BYTE_COUNT_REDIRECT_INFORMATION ByteCount;
|
|||
|
ULONG Length = sizeof(ByteCount);
|
|||
|
NatQueryInformationPortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
&ByteCount,
|
|||
|
&Length,
|
|||
|
NatByteCountRedirectInformation
|
|||
|
);
|
|||
|
printf(
|
|||
|
"NatQueryInformationPortRedirect="
|
|||
|
"%d,{%I64d,%I64d}\n",
|
|||
|
Error,
|
|||
|
ByteCount.BytesForward,
|
|||
|
ByteCount.BytesReverse
|
|||
|
);
|
|||
|
// fall-through
|
|||
|
}
|
|||
|
default: continue;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (Error != WAIT_IO_COMPLETION) {
|
|||
|
Error =
|
|||
|
NatCancelPortRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5]))
|
|||
|
);
|
|||
|
printf("NatCancelPortRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf("NatShutdownTranslator...");
|
|||
|
NatShutdownTranslator(TranslatorHandle);
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestReceiveOnlyDynamicPartialRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Error;
|
|||
|
HANDLE DynamicRedirectHandle;
|
|||
|
|
|||
|
Error =
|
|||
|
NatCreateDynamicPartialRedirect(
|
|||
|
NatRedirectFlagReceiveOnly,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
atol(argv[7]),
|
|||
|
&DynamicRedirectHandle
|
|||
|
);
|
|||
|
printf("NatCreateDynamicPartialRedirect=%d\n", Error);
|
|||
|
if (!Error) {
|
|||
|
printf("Press <Enter> to cancel the dynamic redirect...");
|
|||
|
while (!_kbhit()) { Sleep(1000); }
|
|||
|
Error = NatCancelDynamicPartialRedirect(DynamicRedirectHandle);
|
|||
|
printf("NatCancelDynamicPartialRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestReceiveOnlyDynamicPortRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Error;
|
|||
|
HANDLE DynamicRedirectHandle;
|
|||
|
|
|||
|
Error =
|
|||
|
NatCreateDynamicPortRedirect(
|
|||
|
NatRedirectFlagReceiveOnly,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
htons((USHORT)atol(argv[3])),
|
|||
|
inet_addr(argv[4]),
|
|||
|
htons((USHORT)atol(argv[5])),
|
|||
|
atol(argv[6]),
|
|||
|
&DynamicRedirectHandle
|
|||
|
);
|
|||
|
printf("NatCreateDynamicPortRedirect=%d\n", Error);
|
|||
|
if (!Error) {
|
|||
|
printf("Press <Enter> to cancel the dynamic redirect...");
|
|||
|
while (!_kbhit()) { Sleep(1000); }
|
|||
|
Error = NatCancelDynamicPortRedirect(DynamicRedirectHandle);
|
|||
|
printf("NatCancelDynamicPortRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestRestrictedPartialRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Error;
|
|||
|
HANDLE TranslatorHandle;
|
|||
|
|
|||
|
Error = NatInitializeTranslator(&TranslatorHandle);
|
|||
|
if (Error) {
|
|||
|
printf("NatInitializeTranslator=%d\n", Error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
|
|||
|
Error =
|
|||
|
NatCreateRestrictedPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
0,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
TestApiCompletionRoutine,
|
|||
|
NULL,
|
|||
|
Event
|
|||
|
);
|
|||
|
printf("NatCreateRestrictedPartialRedirect=%d\n", Error);
|
|||
|
if (!Error) {
|
|||
|
for (;;) {
|
|||
|
Error = WaitForSingleObjectEx(Event, 1000, TRUE);
|
|||
|
printf("WaitForSingleObjectEx=%d\n", Error);
|
|||
|
if (Error == WAIT_IO_COMPLETION) {
|
|||
|
break;
|
|||
|
} else if (Error == WAIT_OBJECT_0) {
|
|||
|
NAT_SOURCE_MAPPING_REDIRECT_INFORMATION SourceMapping;
|
|||
|
ULONG Length = sizeof(SourceMapping);
|
|||
|
CHAR src[32], newsrc[32];
|
|||
|
NatQueryInformationPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
&SourceMapping,
|
|||
|
&Length,
|
|||
|
NatSourceMappingRedirectInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
src,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.SourceAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newsrc,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.NewSourceAddress)
|
|||
|
);
|
|||
|
printf("redirect activated: %s->%s\n", src, newsrc);
|
|||
|
}
|
|||
|
if (_kbhit()) {
|
|||
|
switch(getchar()) {
|
|||
|
case 'q': { break; }
|
|||
|
case 's': {
|
|||
|
NAT_BYTE_COUNT_REDIRECT_INFORMATION ByteCount;
|
|||
|
ULONG Length = sizeof(ByteCount);
|
|||
|
NatQueryInformationPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
&ByteCount,
|
|||
|
&Length,
|
|||
|
NatByteCountRedirectInformation
|
|||
|
);
|
|||
|
printf(
|
|||
|
"NatQueryInformationPartialRedirect="
|
|||
|
"%d,{%I64d,%I64d}\n",
|
|||
|
Error,
|
|||
|
ByteCount.BytesForward,
|
|||
|
ByteCount.BytesReverse
|
|||
|
);
|
|||
|
// fall-through
|
|||
|
}
|
|||
|
default: continue;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (Error != WAIT_IO_COMPLETION) {
|
|||
|
Error =
|
|||
|
NatCancelPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6]))
|
|||
|
);
|
|||
|
printf("NatCancelPartialRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf("NatShutdownTranslator...");
|
|||
|
NatShutdownTranslator(TranslatorHandle);
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestDuplicateRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
#define REDIRECT_COUNT 5
|
|||
|
ULONG Count;
|
|||
|
ULONG Error;
|
|||
|
HANDLE EventHandle[REDIRECT_COUNT];
|
|||
|
ULONG i;
|
|||
|
HANDLE TranslatorHandle;
|
|||
|
|
|||
|
Error = NatInitializeTranslator(&TranslatorHandle);
|
|||
|
if (Error) {
|
|||
|
printf("NatInitializeTranslator=%d\n", Error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
for (i = 0, Count = 0; i < REDIRECT_COUNT; i++) {
|
|||
|
EventHandle[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
Error =
|
|||
|
NatCreateRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
0,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
0,
|
|||
|
0,
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
htons((USHORT)(atol(argv[8]) + i)),
|
|||
|
TestApiCompletionRoutine,
|
|||
|
NULL,
|
|||
|
EventHandle[i]
|
|||
|
);
|
|||
|
printf("NatCreateRedirect=%d\n", Error);
|
|||
|
if (!Error) { ++Count; }
|
|||
|
}
|
|||
|
for (;;) {
|
|||
|
ULONG Error2;
|
|||
|
Error =
|
|||
|
WaitForMultipleObjectsEx(
|
|||
|
REDIRECT_COUNT,
|
|||
|
EventHandle,
|
|||
|
FALSE,
|
|||
|
1000,
|
|||
|
TRUE
|
|||
|
);
|
|||
|
printf("WaitForSingleObjectEx=%d\n", Error);
|
|||
|
if (Error == WAIT_IO_COMPLETION) {
|
|||
|
if (!--Count) { break; }
|
|||
|
} else if ((Error - WAIT_OBJECT_0) < REDIRECT_COUNT) {
|
|||
|
NAT_KEY_SESSION_MAPPING_INFORMATION Key;
|
|||
|
ULONG Length = sizeof(Key);
|
|||
|
CHAR src[32], newsrc[32];
|
|||
|
i = Error - WAIT_OBJECT_0;
|
|||
|
Error2 =
|
|||
|
NatLookupAndQueryInformationSessionMapping(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
htons((USHORT)(atol(argv[8]) + i)),
|
|||
|
&Key,
|
|||
|
&Length,
|
|||
|
NatKeySessionMappingInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
src,
|
|||
|
inet_ntoa(*(PIN_ADDR)&Key.SourceAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newsrc,
|
|||
|
inet_ntoa(*(PIN_ADDR)&Key.NewSourceAddress)
|
|||
|
);
|
|||
|
printf("redirect activated[%d]: %s->%s\n", Error2, src, newsrc);
|
|||
|
}
|
|||
|
if (_kbhit()) {
|
|||
|
switch(getchar()) {
|
|||
|
case 'q': { break; }
|
|||
|
case 's': {
|
|||
|
NAT_STATISTICS_SESSION_MAPPING_INFORMATION Statistics;
|
|||
|
for (i = 0; i < REDIRECT_COUNT; i++) {
|
|||
|
ULONG Length = sizeof(Statistics);
|
|||
|
Error2 =
|
|||
|
NatLookupAndQueryInformationSessionMapping(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
htons((USHORT)(atol(argv[8]) + i)),
|
|||
|
&Statistics,
|
|||
|
&Length,
|
|||
|
NatStatisticsSessionMappingInformation
|
|||
|
);
|
|||
|
printf(
|
|||
|
"NatLookupAndQueryInformationSessionMapping=%d,{%I64d,%I64d}\n",
|
|||
|
Error2,
|
|||
|
Statistics.BytesForward,
|
|||
|
Statistics.BytesReverse
|
|||
|
);
|
|||
|
}
|
|||
|
// fall-through
|
|||
|
}
|
|||
|
default: continue;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (Error != WAIT_IO_COMPLETION) {
|
|||
|
for (i = 0; i < REDIRECT_COUNT; i++) {
|
|||
|
Error =
|
|||
|
NatCancelRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
0,
|
|||
|
0,
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
inet_addr(argv[7]),
|
|||
|
htons((USHORT)(atol(argv[8]) + i))
|
|||
|
);
|
|||
|
printf("NatCancelRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf("NatShutdownTranslator...");
|
|||
|
NatShutdownTranslator(TranslatorHandle);
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestDatagramIo(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
SOCKET Socket;
|
|||
|
NhInitializeTraceManagement();
|
|||
|
NhInitializeBufferManagement();
|
|||
|
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
|
|||
|
if (lstrcmpiA(argv[1], "-s") == 0) {
|
|||
|
NhCreateDatagramSocket(
|
|||
|
inet_addr(argv[2]),
|
|||
|
htons(1000),
|
|||
|
&Socket
|
|||
|
);
|
|||
|
NhReadDatagramSocket(
|
|||
|
NULL,
|
|||
|
Socket,
|
|||
|
NULL,
|
|||
|
ReadCompletionRoutine,
|
|||
|
NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
} else if (lstrcmpiA(argv[1], "-c") == 0) {
|
|||
|
PNH_BUFFER Bufferp;
|
|||
|
NhCreateDatagramSocket(
|
|||
|
inet_addr(argv[2]),
|
|||
|
0,
|
|||
|
&Socket
|
|||
|
);
|
|||
|
Bufferp = NhAcquireBuffer();
|
|||
|
lstrcpyA(Bufferp->Buffer, "client-to-server message");
|
|||
|
NhWriteDatagramSocket(
|
|||
|
NULL,
|
|||
|
Socket,
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons(1000),
|
|||
|
Bufferp,
|
|||
|
lstrlenA(Bufferp->Buffer),
|
|||
|
WriteCompletionRoutine,
|
|||
|
NULL,
|
|||
|
NULL
|
|||
|
);
|
|||
|
}
|
|||
|
WaitForSingleObject(Event, INFINITE);
|
|||
|
NhDeleteDatagramSocket(Socket);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestStreamIo(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
SOCKET AcceptedSocket;
|
|||
|
ULONG Error;
|
|||
|
SOCKET ListeningSocket;
|
|||
|
NhInitializeTraceManagement();
|
|||
|
NhInitializeBufferManagement();
|
|||
|
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
Error = NhCreateStreamSocket(INADDR_ANY, htons(1000), &ListeningSocket);
|
|||
|
if (Error != NO_ERROR) {
|
|||
|
printf("error %d creating listening socket\n", Error);
|
|||
|
} else {
|
|||
|
Error = NhCreateStreamSocket(INADDR_NONE, 0, &AcceptedSocket);
|
|||
|
if (Error != NO_ERROR) {
|
|||
|
printf("error %d creating accepted socket\n", Error);
|
|||
|
} else {
|
|||
|
Error = listen(ListeningSocket, SOMAXCONN);
|
|||
|
if (Error == SOCKET_ERROR) {
|
|||
|
printf("error %d listening on socket\n", WSAGetLastError());
|
|||
|
} else {
|
|||
|
Error =
|
|||
|
NhAcceptStreamSocket(
|
|||
|
NULL,
|
|||
|
ListeningSocket,
|
|||
|
AcceptedSocket,
|
|||
|
NULL,
|
|||
|
AcceptCompletionRoutine,
|
|||
|
(PVOID)ListeningSocket,
|
|||
|
(PVOID)AcceptedSocket
|
|||
|
);
|
|||
|
if (Error != NO_ERROR) {
|
|||
|
printf("error %d accepting on socket\n", WSAGetLastError());
|
|||
|
} else {
|
|||
|
WaitForSingleObject(Event, INFINITE);
|
|||
|
}
|
|||
|
}
|
|||
|
NhDeleteStreamSocket(AcceptedSocket);
|
|||
|
}
|
|||
|
NhDeleteStreamSocket(ListeningSocket);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestNotification(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG Error;
|
|||
|
HANDLE TranslatorHandle;
|
|||
|
IO_STATUS_BLOCK IoStatus;
|
|||
|
IP_NAT_REQUEST_NOTIFICATION RequestNotification;
|
|||
|
IP_NAT_ROUTING_FAILURE_NOTIFICATION RoutingFailureNotification;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
Error = NatInitializeTranslator(&TranslatorHandle);
|
|||
|
if (Error) {
|
|||
|
printf("NatInitializeTranslator=%d\n", Error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
printf("waiting for notification...");
|
|||
|
RequestNotification.Code = NatRoutingFailureNotification;
|
|||
|
status =
|
|||
|
NtDeviceIoControlFile(
|
|||
|
TranslatorHandle,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
&IoStatus,
|
|||
|
IOCTL_IP_NAT_REQUEST_NOTIFICATION,
|
|||
|
(PVOID)&RequestNotification,
|
|||
|
sizeof(RequestNotification),
|
|||
|
&RoutingFailureNotification,
|
|||
|
sizeof(RoutingFailureNotification)
|
|||
|
);
|
|||
|
if (status == STATUS_PENDING) {
|
|||
|
NtWaitForSingleObject(TranslatorHandle, FALSE, NULL);
|
|||
|
status = IoStatus.Status;
|
|||
|
}
|
|||
|
{
|
|||
|
CHAR address[32];
|
|||
|
lstrcpyA(
|
|||
|
address,
|
|||
|
inet_ntoa(*(PIN_ADDR)&RoutingFailureNotification.DestinationAddress)
|
|||
|
);
|
|||
|
printf(
|
|||
|
"status=%x,destination=%s,source=%s\n", status, address,
|
|||
|
inet_ntoa(*(PIN_ADDR)&RoutingFailureNotification.SourceAddress)
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
printf("NatShutdownTranslator...");
|
|||
|
NatShutdownTranslator(TranslatorHandle);
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestIoCompletionPartialRedirect(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
IP_NAT_CREATE_REDIRECT CreateRedirect;
|
|||
|
ULONG Error;
|
|||
|
FILE_COMPLETION_INFORMATION CompletionInformation;
|
|||
|
HANDLE IoCompletionHandle;
|
|||
|
IO_STATUS_BLOCK IoStatus;
|
|||
|
IP_NAT_REDIRECT_STATISTICS RedirectStatistics;
|
|||
|
NTSTATUS status;
|
|||
|
HANDLE TranslatorHandle;
|
|||
|
|
|||
|
Error = NatInitializeTranslator(&TranslatorHandle);
|
|||
|
if (Error) {
|
|||
|
printf("NatInitializeTranslator=%d\n", Error);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
Event = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|||
|
|
|||
|
status =
|
|||
|
NtCreateIoCompletion(
|
|||
|
&IoCompletionHandle,
|
|||
|
IO_COMPLETION_ALL_ACCESS,
|
|||
|
NULL,
|
|||
|
0
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
printf("NtCreateIoCompletion=%x\n", status);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
CompletionInformation.Port = IoCompletionHandle;
|
|||
|
CompletionInformation.Key = (PVOID)0xAB01ADE9;
|
|||
|
status =
|
|||
|
NtSetInformationFile(
|
|||
|
TranslatorHandle,
|
|||
|
&IoStatus,
|
|||
|
&CompletionInformation,
|
|||
|
sizeof(CompletionInformation),
|
|||
|
FileCompletionInformation
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
printf("NtSetInformationFile=%x\n", status);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
ZeroMemory(&CreateRedirect, sizeof(CreateRedirect));
|
|||
|
CreateRedirect.Flags =
|
|||
|
IP_NAT_REDIRECT_FLAG_ASYNCHRONOUS|
|
|||
|
IP_NAT_REDIRECT_FLAG_IO_COMPLETION;
|
|||
|
CreateRedirect.Protocol = (UCHAR)atol(argv[2]);
|
|||
|
CreateRedirect.DestinationAddress = inet_addr(argv[3]);
|
|||
|
CreateRedirect.DestinationPort = htons((USHORT)atol(argv[4]));
|
|||
|
CreateRedirect.NewDestinationAddress = inet_addr(argv[5]);
|
|||
|
CreateRedirect.NewDestinationPort = htons((USHORT)atol(argv[6]));
|
|||
|
|
|||
|
status =
|
|||
|
NtDeviceIoControlFile(
|
|||
|
TranslatorHandle,
|
|||
|
Event,
|
|||
|
NULL,
|
|||
|
(PVOID)0x12345678,
|
|||
|
&IoStatus,
|
|||
|
IOCTL_IP_NAT_CREATE_REDIRECT,
|
|||
|
&CreateRedirect,
|
|||
|
sizeof(CreateRedirect),
|
|||
|
&RedirectStatistics,
|
|||
|
sizeof(RedirectStatistics)
|
|||
|
);
|
|||
|
if (status != STATUS_PENDING) {
|
|||
|
printf("NtDeviceIoControlFile=%x\n", status);
|
|||
|
} else {
|
|||
|
PVOID ApcContext;
|
|||
|
PVOID KeyContext;
|
|||
|
LARGE_INTEGER Timeout;
|
|||
|
Timeout.LowPart = (1000 * 1000 * 10);
|
|||
|
Timeout.HighPart = 0;
|
|||
|
Timeout = RtlLargeIntegerNegate(Timeout);
|
|||
|
IoStatus.Status = STATUS_CANCELLED;
|
|||
|
for (;;) {
|
|||
|
status =
|
|||
|
NtRemoveIoCompletion(
|
|||
|
IoCompletionHandle,
|
|||
|
&KeyContext,
|
|||
|
&ApcContext,
|
|||
|
&IoStatus,
|
|||
|
&Timeout
|
|||
|
);
|
|||
|
printf("NtRemoveIoCompletion=%x\n", status);
|
|||
|
if (status == STATUS_SUCCESS &&
|
|||
|
IoStatus.Status != STATUS_PENDING) {
|
|||
|
//
|
|||
|
// Redirect completed.
|
|||
|
//
|
|||
|
printf("redirect %x:%x completed\n", KeyContext, ApcContext);
|
|||
|
break;
|
|||
|
} else if (status == STATUS_SUCCESS &&
|
|||
|
IoStatus.Status == STATUS_PENDING) {
|
|||
|
NAT_SOURCE_MAPPING_REDIRECT_INFORMATION SourceMapping;
|
|||
|
ULONG Length = sizeof(SourceMapping);
|
|||
|
CHAR src[32], newsrc[32];
|
|||
|
//
|
|||
|
// Redirect is activated.
|
|||
|
//
|
|||
|
NatQueryInformationPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
&SourceMapping,
|
|||
|
&Length,
|
|||
|
NatSourceMappingRedirectInformation
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
src,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.SourceAddress)
|
|||
|
);
|
|||
|
lstrcpyA(
|
|||
|
newsrc,
|
|||
|
inet_ntoa(*(PIN_ADDR)&SourceMapping.NewSourceAddress)
|
|||
|
);
|
|||
|
printf(
|
|||
|
"redirect %x:%x activated: %s->%s\n",
|
|||
|
KeyContext, ApcContext, src, newsrc
|
|||
|
);
|
|||
|
}
|
|||
|
if (_kbhit()) {
|
|||
|
switch(getchar()) {
|
|||
|
case 'q': { break; }
|
|||
|
case 's': {
|
|||
|
NAT_BYTE_COUNT_REDIRECT_INFORMATION ByteCount;
|
|||
|
ULONG Length = sizeof(ByteCount);
|
|||
|
NatQueryInformationPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6])),
|
|||
|
&ByteCount,
|
|||
|
&Length,
|
|||
|
NatByteCountRedirectInformation
|
|||
|
);
|
|||
|
printf(
|
|||
|
"NatQueryInformationPartialRedirect="
|
|||
|
"%d,{%I64d,%I64d}\n",
|
|||
|
Error,
|
|||
|
ByteCount.BytesForward,
|
|||
|
ByteCount.BytesReverse
|
|||
|
);
|
|||
|
// fall-through
|
|||
|
}
|
|||
|
default: continue;
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if (status != STATUS_SUCCESS) {
|
|||
|
Error =
|
|||
|
NatCancelPartialRedirect(
|
|||
|
TranslatorHandle,
|
|||
|
(UCHAR)atol(argv[2]),
|
|||
|
inet_addr(argv[3]),
|
|||
|
htons((USHORT)atol(argv[4])),
|
|||
|
inet_addr(argv[5]),
|
|||
|
htons((USHORT)atol(argv[6]))
|
|||
|
);
|
|||
|
printf("NatCancelPartialRedirect=%d\n", Error);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
printf("NatShutdownTranslator...");
|
|||
|
NatShutdownTranslator(TranslatorHandle);
|
|||
|
NtClose(IoCompletionHandle);
|
|||
|
printf("done\n");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
TestPortReservation(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
HANDLE ReservationHandle;
|
|||
|
for (;;) {
|
|||
|
enum {
|
|||
|
PrInitialize,
|
|||
|
PrAcquire,
|
|||
|
PrRelease,
|
|||
|
PrQuit
|
|||
|
} PrOption;
|
|||
|
NTSTATUS Status;
|
|||
|
printf("Options:\n");
|
|||
|
printf("%d - initialize\n", PrInitialize);
|
|||
|
printf("%d - acquire ports\n", PrAcquire);
|
|||
|
printf("%d - release ports\n", PrRelease);
|
|||
|
printf("%d - quit\n", PrQuit);
|
|||
|
printf("> ");
|
|||
|
scanf("%d", &PrOption);
|
|||
|
switch(PrOption) {
|
|||
|
case PrInitialize: {
|
|||
|
USHORT BlockSize;
|
|||
|
printf("enter block size: ");
|
|||
|
scanf("%u", &BlockSize);
|
|||
|
Status =
|
|||
|
NatInitializePortReservation(BlockSize, &ReservationHandle);
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
printf("succeeded.\n");
|
|||
|
} else {
|
|||
|
printf("status: %x\n", Status);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
case PrAcquire: {
|
|||
|
USHORT PortBase;
|
|||
|
USHORT PortCount;
|
|||
|
printf("enter port count: ");
|
|||
|
scanf("%u", &PortCount);
|
|||
|
Status =
|
|||
|
NatAcquirePortReservation(
|
|||
|
ReservationHandle, PortCount, &PortBase
|
|||
|
);
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
printf("succeeded: base port %d\n", ntohs(PortBase));
|
|||
|
} else {
|
|||
|
printf("status: %x\n", Status);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
case PrRelease: {
|
|||
|
USHORT PortBase;
|
|||
|
USHORT PortCount;
|
|||
|
printf("enter base port: ");
|
|||
|
scanf("%u", &PortBase);
|
|||
|
printf("enter port count: ");
|
|||
|
scanf("%u", &PortCount);
|
|||
|
Status =
|
|||
|
NatReleasePortReservation(
|
|||
|
ReservationHandle, ntohs(PortBase), PortCount
|
|||
|
);
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
printf("succeeded\n", ntohs(PortBase));
|
|||
|
} else {
|
|||
|
printf("status: %x\n", Status);
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
case PrQuit: {
|
|||
|
NatShutdownPortReservation(ReservationHandle);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int __cdecl
|
|||
|
main(
|
|||
|
int argc,
|
|||
|
char* argv[]
|
|||
|
)
|
|||
|
{
|
|||
|
WSADATA wd;
|
|||
|
WSAStartup(MAKEWORD(2,2), &wd);
|
|||
|
if (!lstrcmpiA(argv[1], "-accept") && argc == 2) {
|
|||
|
TestStreamIo(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-c") && argc == 4) {
|
|||
|
TestDatagramIo(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-s") && argc == 3) {
|
|||
|
TestDatagramIo(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-n") && argc == 2) {
|
|||
|
TestNotification(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-r") && argc == 11) {
|
|||
|
TestRedirect(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-p") && argc == 7) {
|
|||
|
TestPartialRedirect(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-port") && argc == 6) {
|
|||
|
TestPortRedirect(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-rcvport") && argc == 6) {
|
|||
|
TestReceiveOnlyPortRedirect(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-rp") && argc == 8) {
|
|||
|
TestRestrictedPartialRedirect(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-m") && argc == 9) {
|
|||
|
TestDuplicateRedirect(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-iop") && argc == 7) {
|
|||
|
TestIoCompletionPartialRedirect(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-portreservation") && argc == 2) {
|
|||
|
TestPortReservation(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-rcvdynport") && argc == 7) {
|
|||
|
TestReceiveOnlyDynamicPortRedirect(argc, argv);
|
|||
|
} else if (!lstrcmpiA(argv[1], "-rcvdynp") && argc == 7) {
|
|||
|
TestReceiveOnlyDynamicPartialRedirect(argc, argv);
|
|||
|
} else {
|
|||
|
printf("'nhtest -accept' to test connection-acceptance\n");
|
|||
|
printf("'nhtest -c <client-addr> <server-addr>' to start client\n");
|
|||
|
printf("'nhtest -s <server-addr>' to start server\n");
|
|||
|
printf("'nhtest -n' to wait for notification of routing-failure\n");
|
|||
|
printf("'nhtest -r <p> <da> <dp> <sa> <sp> <da> <dp> <sa> <sp>'\n");
|
|||
|
printf(" creates a full-redirect and waits for activation.\n");
|
|||
|
printf("'nhtest -p <p> <da> <dp> <da> <dp>'\n");
|
|||
|
printf(" creates a partial-redirect and waits for activation.\n");
|
|||
|
printf("'nhtest -port <p> <dp> <da> <dp>'\n");
|
|||
|
printf(" creates a port-redirect and waits for activation.\n");
|
|||
|
printf("'nhtest -rcvport <p> <dp> <da> <dp>'\n");
|
|||
|
printf(" creates a port-redirect for received-packets only\n");
|
|||
|
printf(" and waits for activation.\n");
|
|||
|
printf("'nhtest -rp <p> <da> <dp> <da> <dp> <sa>'\n");
|
|||
|
printf(" creates a restricted partial-redirect\n");
|
|||
|
printf(" and waits for activation.\n");
|
|||
|
printf("'nhtest -m <p> <da> <dp> <da> <dp> <sa> <sp>'\n");
|
|||
|
printf(" creates multiple redirects with the same parameters,\n");
|
|||
|
printf(" and waits for activation.\n");
|
|||
|
printf("'nhtest -iop <p> <da> <dp> <da> <dp>'\n");
|
|||
|
printf(" creates a restricted partial-redirect,\n");
|
|||
|
printf(" associates it with an I/O completion port,\n");
|
|||
|
printf(" and waits for activation.\n");
|
|||
|
printf("'nhtest -portreservation'\n");
|
|||
|
printf(" launches interactive port-reservation API test shell\n");
|
|||
|
printf("'nhtest -rcvdynport <p> <dp> <da> <dp> <backlog>'\n");
|
|||
|
printf(" creates a dynamic port-redirect for received-packets\n");
|
|||
|
printf(" only and waits for interruption.\n");
|
|||
|
printf("'nhtest -rcvdynp <p> <da> <dp> <da> <dp> <backlog>'\n");
|
|||
|
printf(" creates a dynamic partial-redirect for received-packets\n");
|
|||
|
printf(" only and waits for interruption.\n");
|
|||
|
}
|
|||
|
WSACleanup();
|
|||
|
return 0;
|
|||
|
}
|