[KMTEST/TCPIP]

- Add tests checking for TDI_CONNECT behaviour.

svn path=/trunk/; revision=66180
This commit is contained in:
Jérôme Gardou 2015-02-06 10:49:04 +00:00
parent 51d68a3329
commit fcddf62f18
7 changed files with 354 additions and 2 deletions

View file

@ -117,7 +117,7 @@ list(APPEND KMTEST_SOURCE
add_executable(kmtest ${KMTEST_SOURCE})
set_module_type(kmtest win32cui)
target_link_libraries(kmtest ${PSEH_LIB})
add_importlibs(kmtest advapi32 msvcrt kernel32 ntdll)
add_importlibs(kmtest advapi32 ws2_32 msvcrt kernel32 ntdll)
add_target_compile_definitions(kmtest KMT_USER_MODE)
#add_pch(kmtest include/kmt_test.h)
set_target_properties(kmtest PROPERTIES OUTPUT_NAME "kmtest_")

View file

@ -19,6 +19,7 @@ KMT_TESTFUNC Test_RtlSplayTree;
KMT_TESTFUNC Test_RtlUnicodeString;
KMT_TESTFUNC Test_TcpIpIoctl;
KMT_TESTFUNC Test_TcpIpTdi;
KMT_TESTFUNC Test_TcpIpConnect;
/* tests with a leading '-' will not be listed */
const KMT_TEST TestList[] =
@ -34,5 +35,6 @@ const KMT_TEST TestList[] =
{ "RtlSplayTree", Test_RtlSplayTree },
{ "RtlUnicodeString", Test_RtlUnicodeString },
{ "TcpIpTdi", Test_TcpIpTdi },
{ "TcpIpConnect", Test_TcpIpConnect },
{ NULL, NULL },
};

View file

@ -3,6 +3,7 @@ include_directories(../include)
list(APPEND TCPIP_TEST_DRV_SOURCE
../kmtest_drv/kmtest_standalone.c
connect.c
tdi.c
TcpIp_drv.c)

View file

@ -9,6 +9,7 @@
#include "tcpip.h"
extern KMT_MESSAGE_HANDLER TestTdi;
extern KMT_MESSAGE_HANDLER TestConnect;
static struct
{
@ -16,7 +17,8 @@ static struct
PKMT_MESSAGE_HANDLER Handler;
} MessageHandlers[] =
{
{ IOCTL_TEST_TDI, TestTdi },
{ IOCTL_TEST_TDI, TestTdi },
{ IOCTL_TEST_CONNECT, TestConnect },
};
NTSTATUS

View file

@ -6,6 +6,7 @@
*/
#include <kmt_test.h>
#include <winsock2.h>
#include "tcpip.h"
@ -35,3 +36,72 @@ START_TEST(TcpIpTdi)
UnloadTcpIpTestDriver();
}
static
DWORD
WINAPI
AcceptProc(
_In_ LPVOID Parameter)
{
WORD WinsockVersion;
WSADATA WsaData;
int Error;
SOCKET ListenSocket, AcceptSocket;
struct sockaddr_in ListenAddress, AcceptAddress;
int AcceptAddressLength;
HANDLE ReadyToConnectEvent = (HANDLE)Parameter;
/* Initialize winsock */
WinsockVersion = MAKEWORD(2, 0);
Error = WSAStartup(WinsockVersion, &WsaData);
ok(Error == 0, "");
ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ok_bool_true(ListenSocket != INVALID_SOCKET, "socket failed");
ZeroMemory(&ListenAddress, sizeof(ListenAddress));
ListenAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
ListenAddress.sin_port = htons(TEST_CONNECT_SERVER_PORT);
ListenAddress.sin_family = AF_INET;
Error = bind(ListenSocket, (struct sockaddr*)&ListenAddress, sizeof(ListenAddress));
ok(Error == 0, "");
Error = listen(ListenSocket, 1);
ok(Error == 0, "");
SetEvent(ReadyToConnectEvent);
AcceptAddressLength = sizeof(AcceptAddress);
AcceptSocket = accept(ListenSocket, (struct sockaddr*)&AcceptAddress, &AcceptAddressLength);
ok(AcceptSocket != INVALID_SOCKET, "\n");
ok_eq_long(AcceptAddressLength, sizeof(AcceptAddress));
ok_eq_hex(AcceptAddress.sin_addr.S_un.S_addr, inet_addr("127.0.0.1"));
ok_eq_hex(AcceptAddress.sin_port, ntohs(TEST_CONNECT_CLIENT_PORT));
return 0;
}
START_TEST(TcpIpConnect)
{
HANDLE AcceptThread;
HANDLE ReadyToConnectEvent;
ReadyToConnectEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ok(ReadyToConnectEvent != NULL, "\n");
AcceptThread = CreateThread(NULL, 0, AcceptProc, (PVOID)ReadyToConnectEvent, 0, NULL);
ok(AcceptThread != NULL, "");
WaitForSingleObject(ReadyToConnectEvent, INFINITE);
LoadTcpIpTestDriver();
ok(KmtSendToDriver(IOCTL_TEST_CONNECT) == ERROR_SUCCESS, "\n");
WaitForSingleObject(AcceptThread, INFINITE);
UnloadTcpIpTestDriver();
WSACleanup();
}

View file

@ -0,0 +1,272 @@
/*
* PROJECT: ReactOS kernel-mode tests
* LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
* PURPOSE: Kernel-Mode Test Suite for TCPIP.sys
* PROGRAMMER: Jérôme Gardou <jerome.gardou@reactos.org>
*/
#include <kmt_test.h>
#include <tdikrnl.h>
#include <ndk/rtlfuncs.h>
#include <sys/param.h>
#include "tcpip.h"
#define TAG_TEST 'tseT'
#if BYTE_ORDER == LITTLE_ENDIAN
USHORT
htons(USHORT x)
{
return ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8);
}
#else
#define htons(x) (x)
#endif
static
NTSTATUS
NTAPI
IrpCompletionRoutine(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ PIRP Irp,
_In_ PVOID Context)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
static
VOID
TestTcpConnect(void)
{
PIRP Irp;
HANDLE AddressHandle, ConnectionHandle;
FILE_OBJECT* ConnectionFileObject;
DEVICE_OBJECT* DeviceObject;
UNICODE_STRING TcpDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Tcp");
NTSTATUS Status;
PFILE_FULL_EA_INFORMATION FileInfo;
TA_IP_ADDRESS* IpAddress;
TA_IP_ADDRESS ConnectAddress, ReturnAddress;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK StatusBlock;
ULONG FileInfoSize;
IN_ADDR InAddr;
LPCWSTR AddressTerminator;
CONNECTION_CONTEXT ConnectionContext = (CONNECTION_CONTEXT)0xC0CAC01A;
KEVENT Event;
TDI_CONNECTION_INFORMATION RequestInfo, ReturnInfo;
/* Create a TCP address file */
FileInfoSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[TDI_TRANSPORT_ADDRESS_LENGTH]) + 1 + sizeof(TA_IP_ADDRESS);
FileInfo = ExAllocatePoolWithTag(NonPagedPool,
FileInfoSize,
TAG_TEST);
ok(FileInfo != NULL, "");
RtlZeroMemory(FileInfo, FileInfoSize);
FileInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
FileInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
RtlCopyMemory(&FileInfo->EaName[0], TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH);
IpAddress = (PTA_IP_ADDRESS)(&FileInfo->EaName[TDI_TRANSPORT_ADDRESS_LENGTH + 1]);
IpAddress->TAAddressCount = 1;
IpAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
IpAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
IpAddress->Address[0].Address[0].sin_port = htons(TEST_CONNECT_CLIENT_PORT);
Status = RtlIpv4StringToAddressW(L"127.0.0.1", TRUE, &AddressTerminator, &InAddr);
ok_eq_hex(Status, STATUS_SUCCESS);
IpAddress->Address[0].Address[0].in_addr = InAddr.S_un.S_addr;
InitializeObjectAttributes(&ObjectAttributes,
&TcpDeviceName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
Status = ZwCreateFile(
&AddressHandle,
GENERIC_READ | GENERIC_WRITE,
&ObjectAttributes,
&StatusBlock,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
0L,
FileInfo,
FileInfoSize);
ok_eq_hex(Status, STATUS_SUCCESS);
ExFreePoolWithTag(FileInfo, TAG_TEST);
/* Create a TCP connection file */
FileInfoSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[TDI_CONNECTION_CONTEXT_LENGTH]) + 1 + sizeof(CONNECTION_CONTEXT);
FileInfo = ExAllocatePoolWithTag(NonPagedPool,
FileInfoSize,
TAG_TEST);
ok(FileInfo != NULL, "");
RtlZeroMemory(FileInfo, FileInfoSize);
FileInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
FileInfo->EaValueLength = sizeof(CONNECTION_CONTEXT);
RtlCopyMemory(&FileInfo->EaName[0], TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH);
*((CONNECTION_CONTEXT*)&FileInfo->EaName[TDI_CONNECTION_CONTEXT_LENGTH + 1]) = ConnectionContext;
Status = ZwCreateFile(
&ConnectionHandle,
GENERIC_READ | GENERIC_WRITE,
&ObjectAttributes,
&StatusBlock,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
0L,
FileInfo,
FileInfoSize);
ok_eq_hex(Status, STATUS_SUCCESS);
ExFreePoolWithTag(FileInfo, TAG_TEST);
/* Get the file and device object for the upcoming IRPs */
Status = ObReferenceObjectByHandle(
ConnectionHandle,
GENERIC_READ,
*IoFileObjectType,
KernelMode,
(PVOID*)&ConnectionFileObject,
NULL);
ok_eq_hex(Status, STATUS_SUCCESS);
DeviceObject = IoGetRelatedDeviceObject(ConnectionFileObject);
ok(DeviceObject != NULL, "Device object is NULL!\n");
/* Associate the connection file and the address */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
ok(Irp != NULL, "IoAllocateIrp failed.\n");
TdiBuildAssociateAddress(Irp, DeviceObject, ConnectionFileObject, NULL, NULL, AddressHandle);
IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
trace("Associate address IRP is pending.\n");
KeWaitForSingleObject(
&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = Irp->IoStatus.Status;
}
ok_eq_hex(Status, STATUS_SUCCESS);
IoFreeIrp(Irp);
KeClearEvent(&Event);
/* Build the connect IRP. */
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
ok(Irp != NULL, "IoAllocateIrp failed.\n");
/* Prepare the request */
RtlZeroMemory(&RequestInfo, sizeof(RequestInfo));
RtlZeroMemory(&ConnectAddress, sizeof(ConnectAddress));
RequestInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS);
RequestInfo.RemoteAddress = &ConnectAddress;
ConnectAddress.TAAddressCount = 1;
ConnectAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
ConnectAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
ConnectAddress.Address[0].Address[0].sin_port = htons(TEST_CONNECT_SERVER_PORT);
Status = RtlIpv4StringToAddressW(L"127.0.0.1", TRUE, &AddressTerminator, &InAddr);
ConnectAddress.Address[0].Address[0].in_addr = InAddr.S_un.S_addr;
/* See what we will get in exchange */
RtlZeroMemory(&ReturnInfo, sizeof(ReturnInfo));
RtlZeroMemory(&ReturnAddress, sizeof(ReturnAddress));
ReturnInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS);
ReturnInfo.RemoteAddress = &ReturnAddress;
TdiBuildConnect(Irp,
DeviceObject,
ConnectionFileObject,
NULL,
NULL,
NULL,
&RequestInfo,
&ReturnInfo);
IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
trace("Connect IRP is pending.\n");
KeWaitForSingleObject(
&Event,
Executive,
KernelMode,
FALSE,
NULL);
Status = Irp->IoStatus.Status;
trace("Connect IRP completed.\n");
}
ok_eq_hex(Status, STATUS_SUCCESS);
IoFreeIrp(Irp);
/* The IRP doesn't touch the return info */
ok_eq_long(ReturnInfo.RemoteAddressLength, sizeof(TA_IP_ADDRESS));
ok_eq_pointer(ReturnInfo.RemoteAddress, &ReturnAddress);
ok_eq_long(ReturnInfo.OptionsLength, 0);
ok_eq_pointer(ReturnInfo.Options, NULL);
ok_eq_long(ReturnInfo.UserDataLength, 0);
ok_eq_pointer(ReturnInfo.UserData, NULL);
ok_eq_long(ReturnAddress.TAAddressCount, 0);
ok_eq_hex(ReturnAddress.Address[0].AddressType, 0);
ok_eq_hex(ReturnAddress.Address[0].AddressLength, 0);
ok_eq_hex(ReturnAddress.Address[0].Address[0].sin_port, 0);
ok_eq_hex(ReturnAddress.Address[0].Address[0].in_addr, 0);
ObDereferenceObject(ConnectionFileObject);
ZwClose(ConnectionHandle);
ZwClose(AddressHandle);
}
static KSTART_ROUTINE RunTest;
static
VOID
NTAPI
RunTest(
_In_ PVOID Context)
{
UNREFERENCED_PARAMETER(Context);
TestTcpConnect();
}
KMT_MESSAGE_HANDLER TestConnect;
NTSTATUS
TestConnect(
_In_ PDEVICE_OBJECT DeviceObject,
_In_ ULONG ControlCode,
_In_opt_ PVOID Buffer,
_In_ SIZE_T InLength,
_Inout_ PSIZE_T OutLength
)
{
PKTHREAD Thread;
Thread = KmtStartThread(RunTest, NULL);
KmtFinishThread(Thread, NULL);
return STATUS_SUCCESS;
}

View file

@ -1,2 +1,7 @@
#define IOCTL_TEST_TDI 1
#define IOCTL_TEST_CONNECT 2
/* For the TDI_CONNECT test */
#define TEST_CONNECT_SERVER_PORT 12345
#define TEST_CONNECT_CLIENT_PORT 54321