diff options
| author | tumagonx | 2017-08-08 10:54:53 +0700 |
|---|---|---|
| committer | tumagonx | 2017-08-08 10:54:53 +0700 |
| commit | 2acec63b2ed75bf4b71ad257db573c4b8f9639e7 (patch) | |
| tree | a8bea139ddd26116d44ea182b0b8436f2162e6e3 /network.c | |
initial commit
Diffstat (limited to 'network.c')
| -rw-r--r-- | network.c | 715 |
1 files changed, 715 insertions, 0 deletions
diff --git a/network.c b/network.c new file mode 100644 index 0000000..3564db2 --- /dev/null +++ b/network.c | |||
| @@ -0,0 +1,715 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2004 Security Architects Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Module Name: | ||
| 5 | * | ||
| 6 | * network.c | ||
| 7 | * | ||
| 8 | * Abstract: | ||
| 9 | * | ||
| 10 | * This module defines various routines used for hooking the Transport Driver Interface (TDI) network routines. | ||
| 11 | * | ||
| 12 | * Author: | ||
| 13 | * | ||
| 14 | * Eugene Tsyrklevich 12-Mar-2004 | ||
| 15 | * | ||
| 16 | * Revision History: | ||
| 17 | * | ||
| 18 | * None. | ||
| 19 | */ | ||
| 20 | |||
| 21 | |||
| 22 | #include <NTDDK.h> | ||
| 23 | #include <tdikrnl.h> | ||
| 24 | #include <ctype.h> | ||
| 25 | #include "network.h" | ||
| 26 | #include "hookproc.h" | ||
| 27 | #include "userland.h" | ||
| 28 | #include "learn.h" | ||
| 29 | #include "policy.h" | ||
| 30 | #include "log.h" | ||
| 31 | |||
| 32 | |||
| 33 | #ifdef ALLOC_PRAGMA | ||
| 34 | #pragma alloc_text (INIT, InstallNetworkHooks) | ||
| 35 | #pragma alloc_text (PAGE, RemoveNetworkHooks) | ||
| 36 | #endif | ||
| 37 | |||
| 38 | |||
| 39 | //XXX fast io is not handled. TdiDispatchFastDeviceControl | ||
| 40 | |||
| 41 | |||
| 42 | PDEVICE_OBJECT pTcpDevice = NULL, pTcpDeviceOriginal = NULL; | ||
| 43 | PDEVICE_OBJECT pUdpDevice = NULL, pUdpDeviceOriginal = NULL; | ||
| 44 | PDEVICE_OBJECT pIpDevice = NULL, pIpDeviceOriginal = NULL; | ||
| 45 | |||
| 46 | #if DBG | ||
| 47 | int HookedTDIRunning = 0; | ||
| 48 | #endif | ||
| 49 | |||
| 50 | |||
| 51 | /* | ||
| 52 | * TdiStub() XXX remove | ||
| 53 | * | ||
| 54 | * Description: | ||
| 55 | * . | ||
| 56 | * | ||
| 57 | * Parameters: | ||
| 58 | * pIrp - IRP (I/O Request Packet) request. | ||
| 59 | * pIrpStack - . | ||
| 60 | * pCompletion - . | ||
| 61 | * | ||
| 62 | * Returns: | ||
| 63 | * STATUS_SUCCESS. | ||
| 64 | */ | ||
| 65 | |||
| 66 | NTSTATUS | ||
| 67 | TdiStub(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpStack, OUT PTDI_CALLBACK pCompletion, IN ULONG DeviceType) | ||
| 68 | { | ||
| 69 | // LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TdiStub(%x %x %x)\n", pIrp, pIrpStack, pCompletion)); | ||
| 70 | return STATUS_SUCCESS; | ||
| 71 | } | ||
| 72 | |||
| 73 | |||
| 74 | |||
| 75 | NTSTATUS | ||
| 76 | TdiSetEventHandler(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpStack, OUT PTDI_CALLBACK pCompletion, IN ULONG DeviceType) | ||
| 77 | { | ||
| 78 | PTDI_REQUEST_KERNEL_SET_EVENT r = (PTDI_REQUEST_KERNEL_SET_EVENT) &pIrpStack->Parameters; | ||
| 79 | |||
| 80 | |||
| 81 | if (r->EventType != TDI_EVENT_CONNECT) | ||
| 82 | { | ||
| 83 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("%d TdiSetEventHandler: %x %x %x\n", CURRENT_PROCESS_PID, r->EventType, r->EventHandler, r->EventContext)); | ||
| 84 | return STATUS_SUCCESS; | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 88 | if (r->EventHandler == NULL) | ||
| 89 | { | ||
| 90 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("%d TdiSetEventHandler: TDI_EVENT_CONNECT deregistration %x %x %x\n", CURRENT_PROCESS_PID, r->EventHandler, r->EventContext, pIrpStack->FileObject)); | ||
| 91 | return STATUS_SUCCESS; | ||
| 92 | } | ||
| 93 | |||
| 94 | |||
| 95 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("%d TdiSetEventHandler: TDI_EVENT_CONNECT %x %x %x\n", CURRENT_PROCESS_PID, r->EventHandler, r->EventContext, pIrpStack->FileObject)); | ||
| 96 | |||
| 97 | |||
| 98 | return STATUS_SUCCESS; | ||
| 99 | } | ||
| 100 | |||
| 101 | |||
| 102 | |||
| 103 | NTSTATUS | ||
| 104 | TdiConnect(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpStack, OUT PTDI_CALLBACK pCompletion, IN ULONG DeviceType) | ||
| 105 | { | ||
| 106 | /* | ||
| 107 | * IrpSp->Parameters | ||
| 108 | * | ||
| 109 | * Pointer to a TDI_REQUEST_KERNEL_CONNECT structure, equivalent to the TDI_REQUEST_KERNEL structure. | ||
| 110 | */ | ||
| 111 | |||
| 112 | PTDI_REQUEST_KERNEL_CONNECT ConnectInfo = (PTDI_REQUEST_KERNEL_CONNECT) &pIrpStack->Parameters; | ||
| 113 | PTRANSPORT_ADDRESS pTransportAddress; | ||
| 114 | PTA_ADDRESS pAddress; | ||
| 115 | PTDI_ADDRESS_IP ip; | ||
| 116 | CHAR NETWORKNAME[MAX_PATH]; | ||
| 117 | PCHAR FunctionName = "TdiConnect"; | ||
| 118 | |||
| 119 | |||
| 120 | HOOK_ROUTINE_ENTER(); | ||
| 121 | |||
| 122 | |||
| 123 | if (! MmIsAddressValid(ConnectInfo) || | ||
| 124 | ! MmIsAddressValid(ConnectInfo->RequestConnectionInformation) || | ||
| 125 | ! MmIsAddressValid(ConnectInfo->RequestConnectionInformation->RemoteAddress)) | ||
| 126 | { | ||
| 127 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TdiConnect: MmIsAddressValid failed\n")); | ||
| 128 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 129 | } | ||
| 130 | |||
| 131 | |||
| 132 | pTransportAddress = (PTRANSPORT_ADDRESS) ConnectInfo->RequestConnectionInformation->RemoteAddress; | ||
| 133 | |||
| 134 | pAddress = (PTA_ADDRESS) pTransportAddress->Address; | ||
| 135 | |||
| 136 | /* verify that the specified address is a single IP address */ | ||
| 137 | if (pTransportAddress->TAAddressCount != 1 || | ||
| 138 | pAddress->AddressType != TDI_ADDRESS_TYPE_IP || | ||
| 139 | pAddress->AddressLength != TDI_ADDRESS_LENGTH_IP) | ||
| 140 | { | ||
| 141 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("%d TdiConnect: Invalid address detected\n", CURRENT_PROCESS_PID)); | ||
| 142 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 143 | } | ||
| 144 | |||
| 145 | ip = (PTDI_ADDRESS_IP) &pAddress->Address; | ||
| 146 | |||
| 147 | |||
| 148 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("%d TdiConnect(%x %x %x). %d %x:%u (%s)\n", (ULONG) PsGetCurrentProcessId(), pIrp, pIrpStack, pCompletion, pTransportAddress->TAAddressCount, ntohl(ip->in_addr), ntohs(ip->sin_port), inet_ntoa2(ip->in_addr))); | ||
| 149 | |||
| 150 | |||
| 151 | inet_ntoa(ip->in_addr, NETWORKNAME); | ||
| 152 | |||
| 153 | if (LearningMode == FALSE) | ||
| 154 | { | ||
| 155 | POLICY_CHECK_OPTYPE_NAME(NETWORK, DeviceType == NET_DEVICE_TYPE_TCP ? OP_TCPCONNECT : OP_UDPCONNECT); | ||
| 156 | } | ||
| 157 | else | ||
| 158 | { | ||
| 159 | // learning mode | ||
| 160 | AddRule(RULE_NETWORK, NETWORKNAME, DeviceType == NET_DEVICE_TYPE_TCP ? OP_TCPCONNECT : OP_UDPCONNECT); | ||
| 161 | } | ||
| 162 | |||
| 163 | |||
| 164 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 165 | } | ||
| 166 | |||
| 167 | |||
| 168 | |||
| 169 | NTSTATUS | ||
| 170 | TdiListen(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpStack, OUT PTDI_CALLBACK pCompletion, IN ULONG DeviceType) | ||
| 171 | { | ||
| 172 | /* | ||
| 173 | * IrpSp->Parameters | ||
| 174 | * | ||
| 175 | * Pointer to a TDI_REQUEST_KERNEL_LISTEN structure, equivalent to the TDI_REQUEST_KERNEL structure. | ||
| 176 | */ | ||
| 177 | |||
| 178 | PTDI_REQUEST_KERNEL_LISTEN ListenInfo = (PTDI_REQUEST_KERNEL_LISTEN) &pIrpStack->Parameters; | ||
| 179 | PTRANSPORT_ADDRESS pTransportAddress; | ||
| 180 | PTA_ADDRESS pAddress; | ||
| 181 | PTDI_ADDRESS_IP ip; | ||
| 182 | |||
| 183 | |||
| 184 | if (! MmIsAddressValid(ListenInfo) || | ||
| 185 | ! MmIsAddressValid(ListenInfo->RequestConnectionInformation) || | ||
| 186 | ! MmIsAddressValid(ListenInfo->RequestConnectionInformation->RemoteAddress)) | ||
| 187 | { | ||
| 188 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TdiListen: MmIsAddressValid failed\n")); | ||
| 189 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 190 | } | ||
| 191 | |||
| 192 | pTransportAddress = (PTRANSPORT_ADDRESS) ListenInfo->RequestConnectionInformation->RemoteAddress; | ||
| 193 | |||
| 194 | pAddress = (PTA_ADDRESS) pTransportAddress->Address; | ||
| 195 | |||
| 196 | /* verify that the specified address is a single IP address */ | ||
| 197 | if (pTransportAddress->TAAddressCount != 1 || | ||
| 198 | pAddress->AddressType != TDI_ADDRESS_TYPE_IP || | ||
| 199 | pAddress->AddressLength != TDI_ADDRESS_LENGTH_IP) | ||
| 200 | { | ||
| 201 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("%d TdiListen: Invalid address detected\n", CURRENT_PROCESS_PID)); | ||
| 202 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 203 | } | ||
| 204 | |||
| 205 | ip = (PTDI_ADDRESS_IP) &pAddress->Address; | ||
| 206 | |||
| 207 | |||
| 208 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TdiListen(%x %x %x). %d %x:%u (%s)\n", pIrp, pIrpStack, pCompletion, pTransportAddress->TAAddressCount, ntohl(ip->in_addr), ntohs(ip->sin_port), inet_ntoa2(ip->in_addr))); | ||
| 209 | |||
| 210 | |||
| 211 | return STATUS_SUCCESS; | ||
| 212 | } | ||
| 213 | |||
| 214 | |||
| 215 | |||
| 216 | NTSTATUS | ||
| 217 | TdiAccept(IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpStack, OUT PTDI_CALLBACK pCompletion, IN ULONG DeviceType) | ||
| 218 | { | ||
| 219 | /* | ||
| 220 | * IrpSp->Parameters | ||
| 221 | * | ||
| 222 | * Specifies a TDI_REQUEST_KERNEL_ACCEPT structure. | ||
| 223 | */ | ||
| 224 | |||
| 225 | PTDI_REQUEST_KERNEL_ACCEPT AcceptInfo = (PTDI_REQUEST_KERNEL_ACCEPT) &pIrpStack->Parameters; | ||
| 226 | PTRANSPORT_ADDRESS pTransportAddress = (PTRANSPORT_ADDRESS) AcceptInfo->RequestConnectionInformation->RemoteAddress; | ||
| 227 | PTA_ADDRESS pAddress = (PTA_ADDRESS) pTransportAddress->Address; | ||
| 228 | PTDI_ADDRESS_IP ip = (PTDI_ADDRESS_IP) &pAddress->Address; | ||
| 229 | |||
| 230 | |||
| 231 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TdiAccept(%x %x %x). %d %x:%u (%s)\n", pIrp, pIrpStack, pCompletion, pTransportAddress->TAAddressCount, ntohl(ip->in_addr), ntohs(ip->sin_port), inet_ntoa2(ip->in_addr))); | ||
| 232 | |||
| 233 | |||
| 234 | return STATUS_SUCCESS; | ||
| 235 | } | ||
| 236 | |||
| 237 | |||
| 238 | /* | ||
| 239 | NTSTATUS | ||
| 240 | GenericCompletion(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pContext) | ||
| 241 | { | ||
| 242 | if (pIrp->PendingReturned ) | ||
| 243 | IoMarkIrpPending(pIrp); | ||
| 244 | |||
| 245 | return STATUS_SUCCESS; | ||
| 246 | } | ||
| 247 | */ | ||
| 248 | |||
| 249 | |||
| 250 | TDI_IOCTL TdiIoctl[] = | ||
| 251 | { | ||
| 252 | { TDI_ASSOCIATE_ADDRESS, "TDI_ASSOCIATE_ADDRESS", TdiStub }, | ||
| 253 | { TDI_DISASSOCIATE_ADDRESS, "TDI_DISASSOCIATE_ADDRESS", TdiStub }, | ||
| 254 | { TDI_CONNECT, "TDI_CONNECT", TdiConnect }, | ||
| 255 | { TDI_LISTEN, "TDI_LISTEN", TdiListen }, | ||
| 256 | { TDI_ACCEPT, "TDI_ACCEPT", TdiAccept }, | ||
| 257 | { TDI_DISCONNECT, "TDI_DISCONNECT", TdiStub }, | ||
| 258 | { TDI_SEND, "TDI_SEND", TdiStub }, | ||
| 259 | { TDI_RECEIVE, "TDI_RECEIVE", TdiStub }, | ||
| 260 | { TDI_SEND_DATAGRAM, "TDI_SEND_DATAGRAM", TdiStub }, | ||
| 261 | { TDI_RECEIVE_DATAGRAM, "TDI_RECEIVE_DATAGRAM", TdiStub }, | ||
| 262 | { TDI_SET_EVENT_HANDLER, "TDI_SET_EVENT_HANDLER", TdiSetEventHandler }, | ||
| 263 | { TDI_QUERY_INFORMATION, "TDI_QUERY_INFORMATION", TdiStub }, | ||
| 264 | { TDI_SET_INFORMATION, "TDI_SET_INFORMATION", TdiStub }, | ||
| 265 | { TDI_ACTION, "TDI_ACTION", TdiStub }, | ||
| 266 | { TDI_DIRECT_SEND, "TDI_DIRECT_SEND", TdiStub }, | ||
| 267 | { TDI_DIRECT_SEND_DATAGRAM, "TDI_DIRECT_SEND_DATAGRAM", TdiStub }, | ||
| 268 | }; | ||
| 269 | |||
| 270 | |||
| 271 | |||
| 272 | //XXX this function can be called from HookedNtCreateFile (-> NtCreateFile -> IoCreateFile -> ObOpenObjectbyName -> ... -> TDI) | ||
| 273 | BOOLEAN | ||
| 274 | TDIDispatch(PDEVICE_OBJECT pDeviceObject, PIRP pIrp, NTSTATUS *status) | ||
| 275 | { | ||
| 276 | PIO_STACK_LOCATION pIrpStack; | ||
| 277 | TDI_CALLBACK Callback; | ||
| 278 | ULONG DeviceType = 0; | ||
| 279 | |||
| 280 | |||
| 281 | if (pDeviceObject == pTcpDevice) | ||
| 282 | { | ||
| 283 | DeviceType = NET_DEVICE_TYPE_TCP; | ||
| 284 | } | ||
| 285 | else if (pDeviceObject == pUdpDevice) | ||
| 286 | { | ||
| 287 | DeviceType = NET_DEVICE_TYPE_UDP; | ||
| 288 | } | ||
| 289 | else if (pDeviceObject == pIpDevice) | ||
| 290 | { | ||
| 291 | DeviceType = NET_DEVICE_TYPE_IP; | ||
| 292 | } | ||
| 293 | else | ||
| 294 | { | ||
| 295 | return FALSE; | ||
| 296 | } | ||
| 297 | |||
| 298 | |||
| 299 | HOOK_TDI_ENTER_NORC(); | ||
| 300 | |||
| 301 | |||
| 302 | pIrpStack = IoGetCurrentIrpStackLocation(pIrp); | ||
| 303 | |||
| 304 | |||
| 305 | memset(&Callback, 0, sizeof(Callback)); | ||
| 306 | |||
| 307 | // if (pIrpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER) | ||
| 308 | // { | ||
| 309 | // LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("IOCTL_TDI_QUERY_DIRECT_SEND_HANDLER\n")); | ||
| 310 | // } | ||
| 311 | |||
| 312 | switch (pIrpStack->MajorFunction) | ||
| 313 | { | ||
| 314 | case IRP_MJ_CREATE: | ||
| 315 | |||
| 316 | *status = TDICreate(pDeviceObject, pIrp, pIrpStack, &Callback); | ||
| 317 | |||
| 318 | break; | ||
| 319 | |||
| 320 | |||
| 321 | case IRP_MJ_DEVICE_CONTROL: | ||
| 322 | |||
| 323 | // if (DeviceType == NET_DEVICE_TYPE_IP && pIrpStack->Parameters.DeviceIoControl.IoControlCode == 0x120000) | ||
| 324 | if (DeviceType == NET_DEVICE_TYPE_IP) | ||
| 325 | { | ||
| 326 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("%d pIpDevice in use (%x %x %x)\n", (ULONG) PsGetCurrentProcessId(), pIrpStack->Parameters.DeviceIoControl.IoControlCode, pIrpStack->MajorFunction, pIrpStack->MinorFunction)); | ||
| 327 | // *status = STATUS_ACCESS_DENIED; | ||
| 328 | break; | ||
| 329 | } | ||
| 330 | |||
| 331 | if (KeGetCurrentIrql() != PASSIVE_LEVEL || ! NT_SUCCESS(TdiMapUserRequest(pDeviceObject, pIrp, pIrpStack))) | ||
| 332 | { | ||
| 333 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("TdiMapUserRequest failed: %x (irql %d)\n", pIrpStack->Parameters.DeviceIoControl.IoControlCode, KeGetCurrentIrql())); | ||
| 334 | break; | ||
| 335 | } | ||
| 336 | |||
| 337 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("IRP_MJ_DEVICE_CONTROL2 %x\n", pIrpStack->Parameters.DeviceIoControl.IoControlCode)); | ||
| 338 | |||
| 339 | /* FALLTHROUGH */ | ||
| 340 | |||
| 341 | |||
| 342 | case IRP_MJ_INTERNAL_DEVICE_CONTROL: | ||
| 343 | { | ||
| 344 | int i; | ||
| 345 | |||
| 346 | if (DeviceType == NET_DEVICE_TYPE_IP) | ||
| 347 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("%d pIpDevice in use2\n", (ULONG) PsGetCurrentProcessId())); | ||
| 348 | |||
| 349 | for (i = 0; i < sizeof(TdiIoctl) / sizeof(TdiIoctl[0]); i++) | ||
| 350 | { | ||
| 351 | if (TdiIoctl[i].MinorFunction == pIrpStack->MinorFunction) | ||
| 352 | { | ||
| 353 | if (TdiIoctl[i].pfRoutine == TdiStub) | ||
| 354 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("%d IRP_MJ_INTERNAL_DEVICE_CONTROL %s\n", (ULONG) PsGetCurrentProcessId(), TdiIoctl[i].Description)); | ||
| 355 | |||
| 356 | *status = TdiIoctl[i].pfRoutine(pIrp, pIrpStack, &Callback, DeviceType); | ||
| 357 | |||
| 358 | break; | ||
| 359 | } | ||
| 360 | } | ||
| 361 | |||
| 362 | break; | ||
| 363 | } | ||
| 364 | |||
| 365 | case IRP_MJ_CLEANUP: | ||
| 366 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("IRP_MJ_CLEANUP\n")); | ||
| 367 | break; | ||
| 368 | |||
| 369 | case IRP_MJ_CLOSE: | ||
| 370 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("IRP_MJ_CLOSE\n")); | ||
| 371 | break; | ||
| 372 | |||
| 373 | default: | ||
| 374 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("TDIDispatch: default switch case triggered\n")); | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | |||
| 378 | |||
| 379 | if (*status == STATUS_ACCESS_DENIED) | ||
| 380 | { | ||
| 381 | pIrp->IoStatus.Status = STATUS_ACCESS_DENIED; | ||
| 382 | IoCompleteRequest (pIrp, IO_NO_INCREMENT); | ||
| 383 | |||
| 384 | HOOK_TDI_EXIT(TRUE); | ||
| 385 | } | ||
| 386 | |||
| 387 | |||
| 388 | if (Callback.Routine) | ||
| 389 | { | ||
| 390 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TDI Callback.Routine\n")); | ||
| 391 | |||
| 392 | //XXX IoCopyCurrentIrpStackLocationToNext() | ||
| 393 | IoSetCompletionRoutine(pIrp, Callback.Routine, Callback.Context, TRUE, TRUE, TRUE); | ||
| 394 | } | ||
| 395 | else | ||
| 396 | { | ||
| 397 | // Set up a completion routine to handle the bubbling of the "pending" mark of an IRP | ||
| 398 | // IoSetCompletionRoutine(pIrp, GenericCompletion, NULL, TRUE, TRUE, TRUE); | ||
| 399 | |||
| 400 | IoSkipCurrentIrpStackLocation(pIrp); | ||
| 401 | } | ||
| 402 | |||
| 403 | |||
| 404 | if (DeviceType == NET_DEVICE_TYPE_TCP) | ||
| 405 | { | ||
| 406 | *status = IoCallDriver(pTcpDeviceOriginal, pIrp); | ||
| 407 | } | ||
| 408 | else if (DeviceType == NET_DEVICE_TYPE_UDP) | ||
| 409 | { | ||
| 410 | *status = IoCallDriver(pUdpDeviceOriginal, pIrp); | ||
| 411 | } | ||
| 412 | else if (DeviceType == NET_DEVICE_TYPE_IP) | ||
| 413 | { | ||
| 414 | *status = IoCallDriver(pIpDeviceOriginal, pIrp); | ||
| 415 | } | ||
| 416 | else | ||
| 417 | { | ||
| 418 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TDIDispatch: Unknown device type\n")); | ||
| 419 | } | ||
| 420 | |||
| 421 | |||
| 422 | HOOK_TDI_EXIT(TRUE); | ||
| 423 | } | ||
| 424 | |||
| 425 | |||
| 426 | |||
| 427 | NTSTATUS | ||
| 428 | TDICreateAddressCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP pIrp, IN PVOID Context) | ||
| 429 | { | ||
| 430 | return STATUS_SUCCESS; | ||
| 431 | } | ||
| 432 | |||
| 433 | |||
| 434 | |||
| 435 | NTSTATUS | ||
| 436 | TDICreate(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp, IN PIO_STACK_LOCATION pIrpStack, OUT PTDI_CALLBACK pCompletion) | ||
| 437 | { | ||
| 438 | FILE_FULL_EA_INFORMATION *ea = (FILE_FULL_EA_INFORMATION *) pIrp->AssociatedIrp.SystemBuffer; | ||
| 439 | |||
| 440 | |||
| 441 | HOOK_ROUTINE_ENTER(); | ||
| 442 | |||
| 443 | |||
| 444 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("TDICreate(%x %x %x)\n", pIrp, pIrpStack, ea)); | ||
| 445 | |||
| 446 | |||
| 447 | /* | ||
| 448 | * From DDK (TdiDispatchCreate): | ||
| 449 | * | ||
| 450 | * Irp->AssociatedIrp.SystemBuffer | ||
| 451 | * | ||
| 452 | * Pointer to a FILE_FULL_EA_INFORMATION-structured buffer if the file object represents an address or a | ||
| 453 | * connection endpoint to be opened. | ||
| 454 | * For an address, the EaName member is set to the system-defined constant TdiTransportAddress and the EA value | ||
| 455 | * following the EaName array is of type TRANSPORT_ADDRESS, set up by the client to specify the address to be | ||
| 456 | * opened. For some transports, this value can be a symbolic netBIOS or DNS name to be translated by the transport. | ||
| 457 | * | ||
| 458 | * For a connection endpoint, the EaName member is set to the system-defined constant TdiConnectionContext and | ||
| 459 | * the EA value following the EaName array is a client-supplied handle, opaque to the transport driver. The | ||
| 460 | * transport must save this handle and subsequently pass it back to the client's registered event handlers for | ||
| 461 | * this connection. | ||
| 462 | * | ||
| 463 | * If the given file object represents a control channel, this member is NULL. | ||
| 464 | */ | ||
| 465 | |||
| 466 | if (ea == NULL) | ||
| 467 | { | ||
| 468 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("TDICreate: Control channel\n")); | ||
| 469 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 470 | } | ||
| 471 | |||
| 472 | |||
| 473 | if (! MmIsAddressValid(ea) || ea->EaName == NULL || ! MmIsAddressValid(ea->EaName)) | ||
| 474 | { | ||
| 475 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TDICreate: MmIsAddressValid() failed\n")); | ||
| 476 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 477 | } | ||
| 478 | |||
| 479 | |||
| 480 | if (ea->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH && | ||
| 481 | memcmp(ea->EaName, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH) == 0) | ||
| 482 | { | ||
| 483 | CONNECTION_CONTEXT conn_ctx = *(CONNECTION_CONTEXT *) (ea->EaName + ea->EaNameLength + 1); | ||
| 484 | |||
| 485 | if (conn_ctx) | ||
| 486 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("TDI Connection object 0x%x %x\n", conn_ctx, * (PULONG) conn_ctx)); | ||
| 487 | |||
| 488 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 489 | } | ||
| 490 | |||
| 491 | |||
| 492 | // NOTE: for RawIp you can extract protocol number from irps->FileObject->FileName | ||
| 493 | |||
| 494 | if (ea->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH && | ||
| 495 | memcmp(ea->EaName, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH) == 0) | ||
| 496 | { | ||
| 497 | PTRANSPORT_ADDRESS pTransportAddress; | ||
| 498 | PTA_ADDRESS pAddress; | ||
| 499 | PIRP QueryIrp; | ||
| 500 | int i; | ||
| 501 | |||
| 502 | |||
| 503 | pTransportAddress = (PTRANSPORT_ADDRESS) (ea->EaName + ea->EaNameLength + 1); | ||
| 504 | pAddress = pTransportAddress->Address; | ||
| 505 | |||
| 506 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("TDICreate: TDI Address object. Num %d\n", pTransportAddress->TAAddressCount)); | ||
| 507 | |||
| 508 | |||
| 509 | for (i = 0; i < pTransportAddress->TAAddressCount; i++) | ||
| 510 | { | ||
| 511 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("TDICreate: TDI Address %d: %x %x\n", i, pAddress->AddressLength, pAddress->AddressType)); | ||
| 512 | |||
| 513 | |||
| 514 | if (pAddress->AddressType == TDI_ADDRESS_TYPE_IP) | ||
| 515 | { | ||
| 516 | PTDI_ADDRESS_IP ip = (PTDI_ADDRESS_IP) &pAddress->Address; | ||
| 517 | CHAR NETWORKNAME[MAX_PATH]; | ||
| 518 | PCHAR FunctionName = "TDICreate"; | ||
| 519 | |||
| 520 | |||
| 521 | if (ip->sin_port != 0) | ||
| 522 | { | ||
| 523 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("%d TDICreate: Bind IP %x:%u (%s)\n", (ULONG) PsGetCurrentProcessId(), ntohl(ip->in_addr), ntohs(ip->sin_port), inet_ntoa2(ip->in_addr))); | ||
| 524 | |||
| 525 | itoa( ntohs(ip->sin_port), NETWORKNAME, 10 ); | ||
| 526 | //inet_ntoa(ip->in_addr, NETWORKNAME); | ||
| 527 | |||
| 528 | if (LearningMode == FALSE) | ||
| 529 | { | ||
| 530 | POLICY_CHECK_OPTYPE_NAME(NETWORK, OP_BIND); | ||
| 531 | } | ||
| 532 | else | ||
| 533 | { | ||
| 534 | // learning mode | ||
| 535 | AddRule(RULE_NETWORK, NETWORKNAME, OP_BIND); | ||
| 536 | } | ||
| 537 | } | ||
| 538 | else | ||
| 539 | { | ||
| 540 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_VERBOSE, ("%d TDICreate: IP & port are both zero\n", (ULONG) PsGetCurrentProcessId())); | ||
| 541 | } | ||
| 542 | } | ||
| 543 | else | ||
| 544 | { | ||
| 545 | //XXX fail if only IP network addresses are allowed. | ||
| 546 | } | ||
| 547 | |||
| 548 | pAddress += 1; | ||
| 549 | } | ||
| 550 | |||
| 551 | //XXX reread WDM ch 5.3 "COmpleting I/O requests" | ||
| 552 | /* | ||
| 553 | QueryIrp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION, pDeviceObject, | ||
| 554 | pIrpStack->FileObject, NULL, NULL); | ||
| 555 | if (QueryIrp == NULL) | ||
| 556 | { | ||
| 557 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("TDICreate: QueryIrp is NULL\n")); | ||
| 558 | return FALSE; | ||
| 559 | } | ||
| 560 | |||
| 561 | pCompletion->Routine = TDICreateAddressCompletion; | ||
| 562 | pCompletion->Context = QueryIrp; | ||
| 563 | */ | ||
| 564 | } | ||
| 565 | |||
| 566 | |||
| 567 | HOOK_ROUTINE_EXIT(STATUS_SUCCESS); | ||
| 568 | } | ||
| 569 | |||
| 570 | |||
| 571 | |||
| 572 | /* | ||
| 573 | * InstallNetworkHooks() | ||
| 574 | * | ||
| 575 | * Description: | ||
| 576 | * . | ||
| 577 | * | ||
| 578 | * NOTE: Called once during driver initialization (DriverEntry()). | ||
| 579 | * There is no need to cleanup in case a failure since RemoveNetworkHooks() will be called later. | ||
| 580 | * | ||
| 581 | * Parameters: | ||
| 582 | * pDriverObject - pointer to a driver object that represents this driver. | ||
| 583 | * | ||
| 584 | * Returns: | ||
| 585 | * STATUS_SUCCESS to indicate success or an NTSTATUS error code if failed. | ||
| 586 | */ | ||
| 587 | |||
| 588 | NTSTATUS | ||
| 589 | InstallNetworkHooks(PDRIVER_OBJECT pDriverObject) | ||
| 590 | { | ||
| 591 | UNICODE_STRING Name; | ||
| 592 | NTSTATUS status; | ||
| 593 | |||
| 594 | |||
| 595 | status = IoCreateDevice(pDriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, TRUE, &pTcpDevice); | ||
| 596 | if (! NT_SUCCESS(status)) | ||
| 597 | { | ||
| 598 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("InstallNetworkHooks: IoCreateDevice(tcp) failed\n")); | ||
| 599 | return status; | ||
| 600 | } | ||
| 601 | |||
| 602 | |||
| 603 | status = IoCreateDevice(pDriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, TRUE, &pUdpDevice); | ||
| 604 | if (! NT_SUCCESS(status)) | ||
| 605 | { | ||
| 606 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("InstallNetworkHooks: IoCreateDevice(udp) failed\n")); | ||
| 607 | return status; | ||
| 608 | } | ||
| 609 | |||
| 610 | |||
| 611 | status = IoCreateDevice(pDriverObject, 0, NULL, FILE_DEVICE_UNKNOWN, 0, TRUE, &pIpDevice); | ||
| 612 | if (! NT_SUCCESS(status)) | ||
| 613 | { | ||
| 614 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("InstallNetworkHooks: IoCreateDevice(udp) failed\n")); | ||
| 615 | return status; | ||
| 616 | } | ||
| 617 | |||
| 618 | |||
| 619 | RtlInitUnicodeString(&Name, L"\\Device\\Tcp"); | ||
| 620 | |||
| 621 | status = IoAttachDevice(pTcpDevice, &Name, &pTcpDeviceOriginal); | ||
| 622 | if (! NT_SUCCESS(status)) | ||
| 623 | { | ||
| 624 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("InstallNetworkHooks: IoAttachDevice(\\Device\\Tcp) failed\n")); | ||
| 625 | return status; | ||
| 626 | } | ||
| 627 | |||
| 628 | |||
| 629 | RtlInitUnicodeString(&Name, L"\\Device\\Udp"); | ||
| 630 | |||
| 631 | status = IoAttachDevice(pUdpDevice, &Name, &pUdpDeviceOriginal); | ||
| 632 | if (! NT_SUCCESS(status)) | ||
| 633 | { | ||
| 634 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("InstallNetworkHooks: IoAttachDevice(\\Device\\Udp) failed\n")); | ||
| 635 | return status; | ||
| 636 | } | ||
| 637 | |||
| 638 | |||
| 639 | RtlInitUnicodeString(&Name, L"\\Device\\Ip"); | ||
| 640 | |||
| 641 | status = IoAttachDevice(pIpDevice, &Name, &pIpDeviceOriginal); | ||
| 642 | if (! NT_SUCCESS(status)) | ||
| 643 | { | ||
| 644 | LOG(LOG_SS_NETWORK, LOG_PRIORITY_DEBUG, ("InstallNetworkHooks: IoAttachDevice(\\Device\\Ip) failed\n")); | ||
| 645 | return status; | ||
| 646 | } | ||
| 647 | |||
| 648 | |||
| 649 | pTcpDevice->StackSize = pTcpDeviceOriginal->StackSize + 1; | ||
| 650 | // XXX Flags &= ~DO_DEVICE_INITIALIZING; | ||
| 651 | pTcpDevice->Flags |= pTcpDeviceOriginal->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH) & ~DO_DEVICE_INITIALIZING; | ||
| 652 | pTcpDevice->DeviceType = pTcpDeviceOriginal->DeviceType; | ||
| 653 | pTcpDevice->Characteristics = pTcpDeviceOriginal->Characteristics; | ||
| 654 | |||
| 655 | |||
| 656 | pUdpDevice->StackSize = pUdpDeviceOriginal->StackSize + 1; | ||
| 657 | pUdpDevice->Flags |= pUdpDeviceOriginal->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH) & ~DO_DEVICE_INITIALIZING; | ||
| 658 | pUdpDevice->DeviceType = pUdpDeviceOriginal->DeviceType; | ||
| 659 | pUdpDevice->Characteristics = pUdpDeviceOriginal->Characteristics; | ||
| 660 | |||
| 661 | |||
| 662 | pIpDevice->StackSize = pIpDeviceOriginal->StackSize + 1; | ||
| 663 | pIpDevice->Flags |= pIpDeviceOriginal->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE | DO_POWER_INRUSH) & ~DO_DEVICE_INITIALIZING; | ||
| 664 | pIpDevice->DeviceType = pIpDeviceOriginal->DeviceType; | ||
| 665 | pIpDevice->Characteristics = pIpDeviceOriginal->Characteristics; | ||
| 666 | |||
| 667 | |||
| 668 | return STATUS_SUCCESS; | ||
| 669 | } | ||
| 670 | |||
| 671 | |||
| 672 | |||
| 673 | /* | ||
| 674 | * RemoveNetworkHooks() | ||
| 675 | * | ||
| 676 | * Description: | ||
| 677 | * Detach from all network devices. | ||
| 678 | * | ||
| 679 | * Parameters: | ||
| 680 | * pDriverObject - pointer to a driver object that represents this driver. | ||
| 681 | * | ||
| 682 | * Returns: | ||
| 683 | * Nothing. | ||
| 684 | */ | ||
| 685 | |||
| 686 | void | ||
| 687 | RemoveNetworkHooks(PDRIVER_OBJECT pDriverObject) | ||
| 688 | { | ||
| 689 | // int i; | ||
| 690 | |||
| 691 | //XXX is this necessary? we detach so we should not receive any network IRPs | ||
| 692 | // if (pDriverObject && pTcpDevice && pTcpDeviceOriginal) | ||
| 693 | // for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) | ||
| 694 | // pDriverObject->MajorFunction[i] = pTcpDeviceOriginal->DriverObject->MajorFunction[i]; | ||
| 695 | |||
| 696 | |||
| 697 | if (pTcpDeviceOriginal != NULL) | ||
| 698 | IoDetachDevice(pTcpDeviceOriginal); | ||
| 699 | |||
| 700 | if (pUdpDeviceOriginal != NULL) | ||
| 701 | IoDetachDevice(pUdpDeviceOriginal); | ||
| 702 | |||
| 703 | if (pIpDeviceOriginal != NULL) | ||
| 704 | IoDetachDevice(pIpDeviceOriginal); | ||
| 705 | |||
| 706 | |||
| 707 | if (pTcpDevice != NULL) | ||
| 708 | IoDeleteDevice(pTcpDevice); | ||
| 709 | |||
| 710 | if (pUdpDevice != NULL) | ||
| 711 | IoDeleteDevice(pUdpDevice); | ||
| 712 | |||
| 713 | if (pIpDevice != NULL) | ||
| 714 | IoDeleteDevice(pIpDevice); | ||
| 715 | } | ||
