1 /* 2 * PROJECT: ReactOS kernel-mode tests 3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory 4 * PURPOSE: Kernel-Mode Test Suite for TCPIP.sys 5 * PROGRAMMER: Jérôme Gardou <jerome.gardou@reactos.org> 6 */ 7 8 #include <kmt_test.h> 9 #include <tdikrnl.h> 10 #include <ndk/rtlfuncs.h> 11 12 #include <sys/param.h> 13 14 #include "tcpip.h" 15 16 #define TAG_TEST 'tseT' 17 18 #if BYTE_ORDER == LITTLE_ENDIAN 19 USHORT 20 htons(USHORT x) 21 { 22 return ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8); 23 } 24 #else 25 #define htons(x) (x) 26 #endif 27 28 static 29 NTSTATUS 30 NTAPI 31 IrpCompletionRoutine( 32 _In_ PDEVICE_OBJECT DeviceObject, 33 _In_ PIRP Irp, 34 _In_ PVOID Context) 35 { 36 UNREFERENCED_PARAMETER(DeviceObject); 37 UNREFERENCED_PARAMETER(Irp); 38 39 KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE); 40 41 return STATUS_MORE_PROCESSING_REQUIRED; 42 } 43 44 static 45 VOID 46 TestTcpConnect(void) 47 { 48 PIRP Irp; 49 HANDLE AddressHandle, ConnectionHandle; 50 FILE_OBJECT* ConnectionFileObject; 51 DEVICE_OBJECT* DeviceObject; 52 UNICODE_STRING TcpDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Tcp"); 53 NTSTATUS Status; 54 PFILE_FULL_EA_INFORMATION FileInfo; 55 TA_IP_ADDRESS* IpAddress; 56 TA_IP_ADDRESS ConnectAddress, ReturnAddress; 57 OBJECT_ATTRIBUTES ObjectAttributes; 58 IO_STATUS_BLOCK StatusBlock; 59 ULONG FileInfoSize; 60 IN_ADDR InAddr; 61 LPCWSTR AddressTerminator; 62 CONNECTION_CONTEXT ConnectionContext = (CONNECTION_CONTEXT)(ULONG_PTR)0xC0CAC01AC0CAC01AULL; 63 KEVENT Event; 64 TDI_CONNECTION_INFORMATION RequestInfo, ReturnInfo; 65 66 /* Create a TCP address file */ 67 FileInfoSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[TDI_TRANSPORT_ADDRESS_LENGTH]) + 1 + sizeof(TA_IP_ADDRESS); 68 FileInfo = ExAllocatePoolWithTag(NonPagedPool, 69 FileInfoSize, 70 TAG_TEST); 71 ok(FileInfo != NULL, "FileInfo is NULL!\n"); 72 RtlZeroMemory(FileInfo, FileInfoSize); 73 74 FileInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH; 75 FileInfo->EaValueLength = sizeof(TA_IP_ADDRESS); 76 RtlCopyMemory(&FileInfo->EaName[0], TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH); 77 78 IpAddress = (PTA_IP_ADDRESS)(&FileInfo->EaName[TDI_TRANSPORT_ADDRESS_LENGTH + 1]); 79 IpAddress->TAAddressCount = 1; 80 IpAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP; 81 IpAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; 82 IpAddress->Address[0].Address[0].sin_port = htons(TEST_CONNECT_CLIENT_PORT); 83 Status = RtlIpv4StringToAddressW(L"127.0.0.1", TRUE, &AddressTerminator, &InAddr); 84 ok_eq_hex(Status, STATUS_SUCCESS); 85 IpAddress->Address[0].Address[0].in_addr = InAddr.S_un.S_addr; 86 87 InitializeObjectAttributes(&ObjectAttributes, 88 &TcpDeviceName, 89 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 90 NULL, 91 NULL); 92 93 Status = ZwCreateFile( 94 &AddressHandle, 95 GENERIC_READ | GENERIC_WRITE, 96 &ObjectAttributes, 97 &StatusBlock, 98 0, 99 FILE_ATTRIBUTE_NORMAL, 100 FILE_SHARE_READ | FILE_SHARE_WRITE, 101 FILE_OPEN_IF, 102 0L, 103 FileInfo, 104 FileInfoSize); 105 ok_eq_hex(Status, STATUS_SUCCESS); 106 107 ExFreePoolWithTag(FileInfo, TAG_TEST); 108 109 /* Create a TCP connection file */ 110 FileInfoSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[TDI_CONNECTION_CONTEXT_LENGTH]) + 1 + sizeof(CONNECTION_CONTEXT); 111 FileInfo = ExAllocatePoolWithTag(NonPagedPool, 112 FileInfoSize, 113 TAG_TEST); 114 ok(FileInfo != NULL, "FileInfo is NULL!\n"); 115 RtlZeroMemory(FileInfo, FileInfoSize); 116 117 FileInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH; 118 FileInfo->EaValueLength = sizeof(CONNECTION_CONTEXT); 119 RtlCopyMemory(&FileInfo->EaName[0], TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH); 120 *((CONNECTION_CONTEXT*)&FileInfo->EaName[TDI_CONNECTION_CONTEXT_LENGTH + 1]) = ConnectionContext; 121 122 Status = ZwCreateFile( 123 &ConnectionHandle, 124 GENERIC_READ | GENERIC_WRITE, 125 &ObjectAttributes, 126 &StatusBlock, 127 0, 128 FILE_ATTRIBUTE_NORMAL, 129 FILE_SHARE_READ | FILE_SHARE_WRITE, 130 FILE_OPEN_IF, 131 0L, 132 FileInfo, 133 FileInfoSize); 134 ok_eq_hex(Status, STATUS_SUCCESS); 135 136 ExFreePoolWithTag(FileInfo, TAG_TEST); 137 138 /* Get the file and device object for the upcoming IRPs */ 139 Status = ObReferenceObjectByHandle( 140 ConnectionHandle, 141 GENERIC_READ, 142 *IoFileObjectType, 143 KernelMode, 144 (PVOID*)&ConnectionFileObject, 145 NULL); 146 ok_eq_hex(Status, STATUS_SUCCESS); 147 DeviceObject = IoGetRelatedDeviceObject(ConnectionFileObject); 148 ok(DeviceObject != NULL, "Device object is NULL!\n"); 149 150 /* Associate the connection file and the address */ 151 KeInitializeEvent(&Event, NotificationEvent, FALSE); 152 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 153 ok(Irp != NULL, "IoAllocateIrp failed.\n"); 154 155 TdiBuildAssociateAddress(Irp, DeviceObject, ConnectionFileObject, NULL, NULL, AddressHandle); 156 IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE); 157 158 Status = IoCallDriver(DeviceObject, Irp); 159 if (Status == STATUS_PENDING) 160 { 161 trace("Associate address IRP is pending.\n"); 162 KeWaitForSingleObject( 163 &Event, 164 Executive, 165 KernelMode, 166 FALSE, 167 NULL); 168 Status = Irp->IoStatus.Status; 169 } 170 ok_eq_hex(Status, STATUS_SUCCESS); 171 IoFreeIrp(Irp); 172 173 174 KeClearEvent(&Event); 175 176 /* Build the connect IRP. */ 177 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); 178 ok(Irp != NULL, "IoAllocateIrp failed.\n"); 179 180 /* Prepare the request */ 181 RtlZeroMemory(&RequestInfo, sizeof(RequestInfo)); 182 RtlZeroMemory(&ConnectAddress, sizeof(ConnectAddress)); 183 RequestInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS); 184 RequestInfo.RemoteAddress = &ConnectAddress; 185 ConnectAddress.TAAddressCount = 1; 186 ConnectAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP; 187 ConnectAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP; 188 ConnectAddress.Address[0].Address[0].sin_port = htons(TEST_CONNECT_SERVER_PORT); 189 Status = RtlIpv4StringToAddressW(L"127.0.0.1", TRUE, &AddressTerminator, &InAddr); 190 ConnectAddress.Address[0].Address[0].in_addr = InAddr.S_un.S_addr; 191 192 /* See what we will get in exchange */ 193 RtlZeroMemory(&ReturnInfo, sizeof(ReturnInfo)); 194 RtlZeroMemory(&ReturnAddress, sizeof(ReturnAddress)); 195 ReturnInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS); 196 ReturnInfo.RemoteAddress = &ReturnAddress; 197 198 TdiBuildConnect(Irp, 199 DeviceObject, 200 ConnectionFileObject, 201 NULL, 202 NULL, 203 NULL, 204 &RequestInfo, 205 &ReturnInfo); 206 IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE); 207 208 Status = IoCallDriver(DeviceObject, Irp); 209 if (Status == STATUS_PENDING) 210 { 211 trace("Connect IRP is pending.\n"); 212 KeWaitForSingleObject( 213 &Event, 214 Executive, 215 KernelMode, 216 FALSE, 217 NULL); 218 Status = Irp->IoStatus.Status; 219 trace("Connect IRP completed.\n"); 220 } 221 ok_eq_hex(Status, STATUS_SUCCESS); 222 IoFreeIrp(Irp); 223 224 /* The IRP doesn't touch the return info */ 225 ok_eq_long(ReturnInfo.RemoteAddressLength, sizeof(TA_IP_ADDRESS)); 226 ok_eq_pointer(ReturnInfo.RemoteAddress, &ReturnAddress); 227 ok_eq_long(ReturnInfo.OptionsLength, 0); 228 ok_eq_pointer(ReturnInfo.Options, NULL); 229 ok_eq_long(ReturnInfo.UserDataLength, 0); 230 ok_eq_pointer(ReturnInfo.UserData, NULL); 231 232 ok_eq_long(ReturnAddress.TAAddressCount, 0); 233 ok_eq_hex(ReturnAddress.Address[0].AddressType, 0); 234 ok_eq_hex(ReturnAddress.Address[0].AddressLength, 0); 235 ok_eq_hex(ReturnAddress.Address[0].Address[0].sin_port, 0); 236 ok_eq_hex(ReturnAddress.Address[0].Address[0].in_addr, 0); 237 238 ObDereferenceObject(ConnectionFileObject); 239 240 ZwClose(ConnectionHandle); 241 ZwClose(AddressHandle); 242 } 243 244 static KSTART_ROUTINE RunTest; 245 static 246 VOID 247 NTAPI 248 RunTest( 249 _In_ PVOID Context) 250 { 251 UNREFERENCED_PARAMETER(Context); 252 253 TestTcpConnect(); 254 } 255 256 KMT_MESSAGE_HANDLER TestConnect; 257 NTSTATUS 258 TestConnect( 259 _In_ PDEVICE_OBJECT DeviceObject, 260 _In_ ULONG ControlCode, 261 _In_opt_ PVOID Buffer, 262 _In_ SIZE_T InLength, 263 _Inout_ PSIZE_T OutLength 264 ) 265 { 266 PKTHREAD Thread; 267 268 Thread = KmtStartThread(RunTest, NULL); 269 KmtFinishThread(Thread, NULL); 270 271 return STATUS_SUCCESS; 272 } 273