[TCPIP]
[reactos.git] / reactos / drivers / network / tcpip / tcpip / main.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS TCP/IP protocol driver
4 * FILE: tcpip/main.c
5 * PURPOSE: Driver entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/08-2000 Created
9 */
10
11 #include "precomp.h"
12
13 #include <dispatch.h>
14 #include <fileobjs.h>
15
16 PDEVICE_OBJECT TCPDeviceObject = NULL;
17 PDEVICE_OBJECT UDPDeviceObject = NULL;
18 PDEVICE_OBJECT IPDeviceObject = NULL;
19 PDEVICE_OBJECT RawIPDeviceObject = NULL;
20 NDIS_HANDLE GlobalPacketPool = NULL;
21 NDIS_HANDLE GlobalBufferPool = NULL;
22 KSPIN_LOCK EntityListLock;
23 TDIEntityInfo *EntityList = NULL;
24 ULONG EntityCount = 0;
25 ULONG EntityMax = 0;
26 UDP_STATISTICS UDPStats;
27
28 /* Network timers */
29 KTIMER IPTimer;
30 KDPC IPTimeoutDpc;
31
32 VOID TiWriteErrorLog(
33 PDRIVER_OBJECT DriverContext,
34 NTSTATUS ErrorCode,
35 ULONG UniqueErrorValue,
36 NTSTATUS FinalStatus,
37 PWSTR String,
38 ULONG DumpDataCount,
39 PULONG DumpData)
40 /*
41 * FUNCTION: Writes an error log entry
42 * ARGUMENTS:
43 * DriverContext = Pointer to the driver or device object
44 * ErrorCode = An error code to put in the log entry
45 * UniqueErrorValue = UniqueErrorValue in the error log packet
46 * FinalStatus = FinalStatus in the error log packet
47 * String = If not NULL, a pointer to a string to put in log
48 * entry
49 * DumpDataCount = Number of ULONGs of dump data
50 * DumpData = Pointer to dump data for the log entry
51 */
52 {
53 #if 0
54 PIO_ERROR_LOG_PACKET LogEntry;
55 UCHAR EntrySize;
56 ULONG StringSize;
57 PUCHAR pString;
58 static WCHAR DriverName[] = L"TCP/IP";
59
60 EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
61 (DumpDataCount * sizeof(ULONG)) + sizeof(DriverName);
62
63 if (String) {
64 StringSize = (wcslen(String) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
65 EntrySize += (UCHAR)StringSize;
66 }
67
68 LogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
69 DriverContext, EntrySize);
70
71 if (LogEntry) {
72 LogEntry->MajorFunctionCode = -1;
73 LogEntry->RetryCount = -1;
74 LogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
75 LogEntry->NumberOfStrings = (String == NULL) ? 1 : 2;
76 LogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) + (DumpDataCount-1) * sizeof(ULONG);
77 LogEntry->EventCategory = 0;
78 LogEntry->ErrorCode = ErrorCode;
79 LogEntry->UniqueErrorValue = UniqueErrorValue;
80 LogEntry->FinalStatus = FinalStatus;
81 LogEntry->SequenceNumber = -1;
82 LogEntry->IoControlCode = 0;
83
84 if (DumpDataCount)
85 RtlCopyMemory(LogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
86
87 pString = ((PUCHAR)LogEntry) + LogEntry->StringOffset;
88 RtlCopyMemory(pString, DriverName, sizeof(DriverName));
89 pString += sizeof(DriverName);
90
91 if (String)
92 RtlCopyMemory(pString, String, StringSize);
93
94 IoWriteErrorLogEntry(LogEntry);
95 }
96 #endif
97 }
98
99 /*
100 * FUNCTION: Creates a file object
101 * ARGUMENTS:
102 * DeviceObject = Pointer to a device object for this driver
103 * Irp = Pointer to a I/O request packet
104 * RETURNS:
105 * Status of the operation
106 */
107
108 NTSTATUS TiCreateFileObject(
109 PDEVICE_OBJECT DeviceObject,
110 PIRP Irp)
111 {
112 PFILE_FULL_EA_INFORMATION EaInfo;
113 PTRANSPORT_CONTEXT Context;
114 PIO_STACK_LOCATION IrpSp;
115 PTA_IP_ADDRESS Address;
116 TDI_REQUEST Request;
117 PVOID ClientContext;
118 NTSTATUS Status;
119 ULONG Protocol;
120 BOOLEAN Shared;
121
122 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
123
124 EaInfo = Irp->AssociatedIrp.SystemBuffer;
125
126 /* Parameter check */
127 /* No EA information means that we're opening for SET/QUERY_INFORMATION
128 * style calls. */
129
130 /* Allocate resources here. We release them again if something failed */
131 Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSPORT_CONTEXT),
132 TRANS_CONTEXT_TAG);
133 if (!Context)
134 {
135 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
136 return STATUS_INSUFFICIENT_RESOURCES;
137 }
138
139 Context->CancelIrps = FALSE;
140
141 IrpSp = IoGetCurrentIrpStackLocation(Irp);
142 IrpSp->FileObject->FsContext = Context;
143 Request.RequestContext = Irp;
144
145 /* Branch to the right handler */
146 if (EaInfo &&
147 (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
148 (RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress,
149 TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH))
150 {
151 /* This is a request to open an address */
152
153
154 /* XXX This should probably be done in IoCreateFile() */
155 /* Parameter checks */
156
157 Address = (PTA_IP_ADDRESS)(EaInfo->EaName + EaInfo->EaNameLength + 1); //0-term
158
159 if ((EaInfo->EaValueLength < sizeof(TA_IP_ADDRESS)) ||
160 (Address->TAAddressCount != 1) ||
161 (Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) ||
162 (Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP))
163 {
164 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid:\n"));
165 TI_DbgPrint(MIN_TRACE, ("AddressCount: %d\n", Address->TAAddressCount));
166 if( Address->TAAddressCount == 1 )
167 {
168 TI_DbgPrint(MIN_TRACE, ("AddressLength: %u\n",
169 Address->Address[0].AddressLength));
170 TI_DbgPrint(MIN_TRACE, ("AddressType: %u\n",
171 Address->Address[0].AddressType));
172 }
173
174 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
175 return STATUS_INVALID_PARAMETER;
176 }
177
178 /* Open address file object */
179
180 /* Protocol depends on device object so find the protocol */
181 if (DeviceObject == TCPDeviceObject)
182 Protocol = IPPROTO_TCP;
183 else if (DeviceObject == UDPDeviceObject)
184 Protocol = IPPROTO_UDP;
185 else if (DeviceObject == IPDeviceObject)
186 Protocol = IPPROTO_RAW;
187 else if (DeviceObject == RawIPDeviceObject)
188 {
189 Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
190 if (!NT_SUCCESS(Status))
191 {
192 TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
193 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
194 return STATUS_INVALID_PARAMETER;
195 }
196 }
197 else
198 {
199 TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
200 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
201 return STATUS_INVALID_PARAMETER;
202 }
203
204 Shared = (IrpSp->Parameters.Create.ShareAccess != 0);
205
206 Status = FileOpenAddress(&Request, Address, Protocol, Shared, NULL);
207 if (NT_SUCCESS(Status))
208 {
209 IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
210 Context->Handle.AddressHandle = Request.Handle.AddressHandle;
211 }
212
213 }
214 else if (EaInfo &&
215 (EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
216 (RtlCompareMemory
217 (&EaInfo->EaName, TdiConnectionContext,
218 TDI_CONNECTION_CONTEXT_LENGTH) ==
219 TDI_CONNECTION_CONTEXT_LENGTH))
220 {
221 /* This is a request to open a connection endpoint */
222
223 /* Parameter checks */
224
225 if (EaInfo->EaValueLength < sizeof(PVOID))
226 {
227 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
228 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
229 return STATUS_INVALID_PARAMETER;
230 }
231
232 /* Can only do connection oriented communication using TCP */
233
234 if (DeviceObject != TCPDeviceObject)
235 {
236 TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
237 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
238 return STATUS_INVALID_PARAMETER;
239 }
240
241 ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength));
242
243 /* Open connection endpoint file object */
244
245 Status = FileOpenConnection(&Request, ClientContext);
246 if (NT_SUCCESS(Status))
247 {
248 IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
249 Context->Handle.ConnectionContext = Request.Handle.ConnectionContext;
250 }
251 }
252 else
253 {
254 /* This is a request to open a control connection */
255 Status = FileOpenControlChannel(&Request);
256 if (NT_SUCCESS(Status))
257 {
258 IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
259 Context->Handle.ControlChannel = Request.Handle.ControlChannel;
260 }
261 }
262
263 if (!NT_SUCCESS(Status))
264 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
265
266 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
267
268 Irp->IoStatus.Status = Status;
269 return Status;
270 }
271
272
273 /*
274 * FUNCTION: Releases resources used by a file object
275 * ARGUMENTS:
276 * DeviceObject = Pointer to a device object for this driver
277 * Irp = Pointer to a I/O request packet
278 * RETURNS:
279 * Status of the operation
280 * NOTES:
281 * This function does not pend
282 */
283 NTSTATUS TiCloseFileObject(
284 PDEVICE_OBJECT DeviceObject,
285 PIRP Irp)
286 {
287 PIO_STACK_LOCATION IrpSp;
288 PTRANSPORT_CONTEXT Context;
289 TDI_REQUEST Request;
290 NTSTATUS Status;
291
292 IrpSp = IoGetCurrentIrpStackLocation(Irp);
293 Context = IrpSp->FileObject->FsContext;
294 if (!Context)
295 {
296 TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
297 return STATUS_INVALID_PARAMETER;
298 }
299
300 switch ((ULONG_PTR)IrpSp->FileObject->FsContext2)
301 {
302 case TDI_TRANSPORT_ADDRESS_FILE:
303 Request.Handle.AddressHandle = Context->Handle.AddressHandle;
304 Status = FileCloseAddress(&Request);
305 break;
306
307 case TDI_CONNECTION_FILE:
308 Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
309 Status = FileCloseConnection(&Request);
310 break;
311
312 case TDI_CONTROL_CHANNEL_FILE:
313 Request.Handle.ControlChannel = Context->Handle.ControlChannel;
314 Status = FileCloseControlChannel(&Request);
315 break;
316
317 default:
318 Status = STATUS_INVALID_PARAMETER;
319 break;
320 }
321
322 if (NT_SUCCESS(Status))
323 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
324
325 Irp->IoStatus.Status = Status;
326
327 return Irp->IoStatus.Status;
328 }
329
330
331 NTSTATUS NTAPI
332 TiDispatchOpenClose(
333 IN PDEVICE_OBJECT DeviceObject,
334 IN PIRP Irp)
335 /*
336 * FUNCTION: Main dispath routine
337 * ARGUMENTS:
338 * DeviceObject = Pointer to a device object for this driver
339 * Irp = Pointer to a I/O request packet
340 * RETURNS:
341 * Status of the operation
342 */
343 {
344 PIO_STACK_LOCATION IrpSp;
345 NTSTATUS Status;
346
347 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
348
349 IrpSp = IoGetCurrentIrpStackLocation(Irp);
350
351 switch (IrpSp->MajorFunction) {
352 /* Open an address file, connection endpoint, or control connection */
353 case IRP_MJ_CREATE:
354 Status = TiCreateFileObject(DeviceObject, Irp);
355 break;
356
357 /* Close an address file, connection endpoint, or control connection */
358 case IRP_MJ_CLOSE:
359 Status = TiCloseFileObject(DeviceObject, Irp);
360 break;
361
362 default:
363 Status = STATUS_INVALID_DEVICE_REQUEST;
364 }
365
366 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
367
368 return IRPFinish( Irp, Status );
369 }
370
371
372 NTSTATUS NTAPI
373 TiDispatchInternal(
374 PDEVICE_OBJECT DeviceObject,
375 PIRP Irp)
376 /*
377 * FUNCTION: Internal IOCTL dispatch routine
378 * ARGUMENTS:
379 * DeviceObject = Pointer to a device object for this driver
380 * Irp = Pointer to a I/O request packet
381 * RETURNS:
382 * Status of the operation
383 */
384 {
385 NTSTATUS Status;
386 BOOLEAN Complete = TRUE;
387 PIO_STACK_LOCATION IrpSp;
388
389 IrpSp = IoGetCurrentIrpStackLocation(Irp);
390
391 TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
392 DeviceObject, Irp, IrpSp->MinorFunction));
393
394 Irp->IoStatus.Status = STATUS_SUCCESS;
395 Irp->IoStatus.Information = 0;
396
397 switch (IrpSp->MinorFunction) {
398 case TDI_RECEIVE:
399 Status = DispTdiReceive(Irp);
400 Complete = FALSE;
401 break;
402
403 case TDI_RECEIVE_DATAGRAM:
404 Status = DispTdiReceiveDatagram(Irp);
405 Complete = FALSE;
406 break;
407
408 case TDI_SEND:
409 Status = DispTdiSend(Irp);
410 Complete = FALSE; /* Completed in DispTdiSend */
411 break;
412
413 case TDI_SEND_DATAGRAM:
414 Status = DispTdiSendDatagram(Irp);
415 Complete = FALSE;
416 break;
417
418 case TDI_ACCEPT:
419 Status = DispTdiAccept(Irp);
420 break;
421
422 case TDI_LISTEN:
423 Status = DispTdiListen(Irp);
424 Complete = FALSE;
425 break;
426
427 case TDI_CONNECT:
428 Status = DispTdiConnect(Irp);
429 Complete = FALSE; /* Completed by the TCP event handler */
430 break;
431
432 case TDI_DISCONNECT:
433 Status = DispTdiDisconnect(Irp);
434 Complete = FALSE;
435 break;
436
437 case TDI_ASSOCIATE_ADDRESS:
438 Status = DispTdiAssociateAddress(Irp);
439 break;
440
441 case TDI_DISASSOCIATE_ADDRESS:
442 Status = DispTdiDisassociateAddress(Irp);
443 break;
444
445 case TDI_QUERY_INFORMATION:
446 Status = DispTdiQueryInformation(DeviceObject, Irp);
447 break;
448
449 case TDI_SET_INFORMATION:
450 Status = DispTdiSetInformation(Irp);
451 break;
452
453 case TDI_SET_EVENT_HANDLER:
454 Status = DispTdiSetEventHandler(Irp);
455 break;
456
457 case TDI_ACTION:
458 Status = STATUS_SUCCESS;
459 break;
460
461 /* An unsupported IOCTL code was submitted */
462 default:
463 Status = STATUS_INVALID_DEVICE_REQUEST;
464 }
465
466 TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status));
467
468 if( Complete )
469 IRPFinish( Irp, Status );
470
471 return Status;
472 }
473
474
475 NTSTATUS NTAPI
476 TiDispatch(
477 PDEVICE_OBJECT DeviceObject,
478 PIRP Irp)
479 /*
480 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
481 * ARGUMENTS:
482 * DeviceObject = Pointer to a device object for this driver
483 * Irp = Pointer to a I/O request packet
484 * RETURNS:
485 * Status of the operation
486 */
487 {
488 NTSTATUS Status;
489 PIO_STACK_LOCATION IrpSp;
490
491 IrpSp = IoGetCurrentIrpStackLocation(Irp);
492
493 TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp));
494
495 Irp->IoStatus.Information = 0;
496
497 #if 0
498 Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp);
499 if (NT_SUCCESS(Status)) {
500 TiDispatchInternal(DeviceObject, Irp);
501 Status = STATUS_PENDING;
502 } else {
503 #else
504 if (TRUE) {
505 #endif
506 /* See if this request is TCP/IP specific */
507 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
508 case IOCTL_TCP_QUERY_INFORMATION_EX:
509 TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n"));
510 Status = DispTdiQueryInformationEx(Irp, IrpSp);
511 break;
512
513 case IOCTL_TCP_SET_INFORMATION_EX:
514 TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n"));
515 Status = DispTdiSetInformationEx(Irp, IrpSp);
516 break;
517
518 case IOCTL_SET_IP_ADDRESS:
519 TI_DbgPrint(MIN_TRACE, ("SET_IP_ADDRESS\n"));
520 Status = DispTdiSetIPAddress(Irp, IrpSp);
521 break;
522
523 case IOCTL_DELETE_IP_ADDRESS:
524 TI_DbgPrint(MIN_TRACE, ("DELETE_IP_ADDRESS\n"));
525 Status = DispTdiDeleteIPAddress(Irp, IrpSp);
526 break;
527
528 case IOCTL_QUERY_IP_HW_ADDRESS:
529 TI_DbgPrint(MIN_TRACE, ("QUERY_IP_HW_ADDRESS\n"));
530 Status = DispTdiQueryIpHwAddress(Irp, IrpSp);
531 break;
532
533 default:
534 TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
535 IrpSp->Parameters.DeviceIoControl.IoControlCode));
536 Status = STATUS_NOT_IMPLEMENTED;
537 break;
538 }
539 }
540
541 TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status));
542
543 return IRPFinish( Irp, Status );
544 }
545
546
547 VOID NTAPI TiUnload(
548 PDRIVER_OBJECT DriverObject)
549 /*
550 * FUNCTION: Unloads the driver
551 * ARGUMENTS:
552 * DriverObject = Pointer to driver object created by the system
553 */
554 {
555 #if DBG
556 KIRQL OldIrql;
557
558 TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
559 if (!IsListEmpty(&AddressFileListHead)) {
560 TI_DbgPrint(MIN_TRACE, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
561 }
562 TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
563 #endif
564 /* Cancel timer */
565 KeCancelTimer(&IPTimer);
566
567 /* Unregister loopback adapter */
568 LoopUnregisterAdapter(NULL);
569
570 /* Unregister protocol with NDIS */
571 LANUnregisterProtocol();
572
573 /* Shutdown transport level protocol subsystems */
574 TCPShutdown();
575 UDPShutdown();
576 RawIPShutdown();
577 ICMPShutdown();
578
579 /* Shutdown network level protocol subsystem */
580 IPShutdown();
581
582 /* Free NDIS buffer descriptors */
583 if (GlobalBufferPool)
584 NdisFreeBufferPool(GlobalBufferPool);
585
586 /* Free NDIS packet descriptors */
587 if (GlobalPacketPool)
588 NdisFreePacketPool(GlobalPacketPool);
589
590 /* Release all device objects */
591
592 if (TCPDeviceObject)
593 IoDeleteDevice(TCPDeviceObject);
594
595 if (UDPDeviceObject)
596 IoDeleteDevice(UDPDeviceObject);
597
598 if (RawIPDeviceObject)
599 IoDeleteDevice(RawIPDeviceObject);
600
601 if (IPDeviceObject) {
602 ChewShutdown();
603 IoDeleteDevice(IPDeviceObject);
604 }
605
606 if (EntityList)
607 ExFreePoolWithTag(EntityList, TDI_ENTITY_TAG);
608
609 TI_DbgPrint(MAX_TRACE, ("[TCPIP, TiUnload] Leaving.\n"));
610 }
611
612 NTSTATUS NTAPI
613 DriverEntry(
614 PDRIVER_OBJECT DriverObject,
615 PUNICODE_STRING RegistryPath)
616 /*
617 * FUNCTION: Main driver entry point
618 * ARGUMENTS:
619 * DriverObject = Pointer to a driver object for this driver
620 * RegistryPath = Registry node for configuration parameters
621 * RETURNS:
622 * Status of driver initialization
623 */
624 {
625 NTSTATUS Status;
626 UNICODE_STRING strIpDeviceName = RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME);
627 UNICODE_STRING strRawDeviceName = RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME);
628 UNICODE_STRING strUdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
629 UNICODE_STRING strTcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
630 UNICODE_STRING strNdisDeviceName = RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME);
631 NDIS_STATUS NdisStatus;
632 LARGE_INTEGER DueTime;
633
634 TI_DbgPrint(MAX_TRACE, ("[TCPIP, DriverEntry] Called\n"));
635
636 /* TdiInitialize() ? */
637
638 /* FIXME: Create symbolic links in Win32 namespace */
639
640 /* Initialize our periodic timer and its associated DPC object. When the
641 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
642 KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL);
643 KeInitializeTimer(&IPTimer);
644
645 /* Create IP device object */
646 Status = IoCreateDevice(DriverObject, 0, &strIpDeviceName,
647 FILE_DEVICE_NETWORK, 0, FALSE, &IPDeviceObject);
648 if (!NT_SUCCESS(Status)) {
649 TI_DbgPrint(MIN_TRACE, ("Failed to create IP device object. Status (0x%X).\n", Status));
650 TiUnload(DriverObject);
651 return Status;
652 }
653
654 ChewInit( IPDeviceObject );
655
656 /* Create RawIP device object */
657 Status = IoCreateDevice(DriverObject, 0, &strRawDeviceName,
658 FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject);
659 if (!NT_SUCCESS(Status)) {
660 TI_DbgPrint(MIN_TRACE, ("Failed to create RawIP device object. Status (0x%X).\n", Status));
661 TiUnload(DriverObject);
662 return Status;
663 }
664
665 /* Create UDP device object */
666 Status = IoCreateDevice(DriverObject, 0, &strUdpDeviceName,
667 FILE_DEVICE_NETWORK, 0, FALSE, &UDPDeviceObject);
668 if (!NT_SUCCESS(Status)) {
669 TI_DbgPrint(MIN_TRACE, ("Failed to create UDP device object. Status (0x%X).\n", Status));
670 TiUnload(DriverObject);
671 return Status;
672 }
673
674 /* Create TCP device object */
675 Status = IoCreateDevice(DriverObject, 0, &strTcpDeviceName,
676 FILE_DEVICE_NETWORK, 0, FALSE, &TCPDeviceObject);
677 if (!NT_SUCCESS(Status)) {
678 TI_DbgPrint(MIN_TRACE, ("Failed to create TCP device object. Status (0x%X).\n", Status));
679 TiUnload(DriverObject);
680 return Status;
681 }
682
683 /* Setup network layer and transport layer entities */
684 KeInitializeSpinLock(&EntityListLock);
685 EntityList = ExAllocatePoolWithTag(NonPagedPool,
686 sizeof(TDIEntityID) * MAX_TDI_ENTITIES,
687 TDI_ENTITY_TAG );
688 if (!EntityList) {
689 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
690 TiUnload(DriverObject);
691 return STATUS_INSUFFICIENT_RESOURCES;
692 }
693
694 EntityCount = 0;
695 EntityMax = MAX_TDI_ENTITIES;
696
697 /* Allocate NDIS packet descriptors */
698 NdisAllocatePacketPoolEx(&NdisStatus, &GlobalPacketPool, 500, 1500, sizeof(PACKET_CONTEXT));
699 if (NdisStatus != NDIS_STATUS_SUCCESS) {
700 TiUnload(DriverObject);
701 return STATUS_INSUFFICIENT_RESOURCES;
702 }
703
704 /* Allocate NDIS buffer descriptors */
705 NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 2000);
706 if (NdisStatus != NDIS_STATUS_SUCCESS) {
707 TiUnload(DriverObject);
708 return STATUS_INSUFFICIENT_RESOURCES;
709 }
710
711 /* Initialize address file list and protecting spin lock */
712 InitializeListHead(&AddressFileListHead);
713 KeInitializeSpinLock(&AddressFileListLock);
714
715 /* Initialize connection endpoint list and protecting spin lock */
716 InitializeListHead(&ConnectionEndpointListHead);
717 KeInitializeSpinLock(&ConnectionEndpointListLock);
718
719 /* Initialize interface list and protecting spin lock */
720 InitializeListHead(&InterfaceListHead);
721 KeInitializeSpinLock(&InterfaceListLock);
722
723 /* Initialize network level protocol subsystem */
724 IPStartup(RegistryPath);
725
726 /* Initialize transport level protocol subsystems */
727 Status = RawIPStartup();
728 if( !NT_SUCCESS(Status) ) {
729 TiUnload(DriverObject);
730 return Status;
731 }
732
733 Status = UDPStartup();
734 if( !NT_SUCCESS(Status) ) {
735 TiUnload(DriverObject);
736 return Status;
737 }
738
739 Status = TCPStartup();
740 if( !NT_SUCCESS(Status) ) {
741 TiUnload(DriverObject);
742 return Status;
743 }
744
745 Status = ICMPStartup();
746 if( !NT_SUCCESS(Status) ) {
747 TiUnload(DriverObject);
748 return Status;
749 }
750
751 /* Use direct I/O */
752 IPDeviceObject->Flags |= DO_DIRECT_IO;
753 RawIPDeviceObject->Flags |= DO_DIRECT_IO;
754 UDPDeviceObject->Flags |= DO_DIRECT_IO;
755 TCPDeviceObject->Flags |= DO_DIRECT_IO;
756
757 /* Initialize the driver object with this driver's entry points */
758 DriverObject->MajorFunction[IRP_MJ_CREATE] = TiDispatchOpenClose;
759 DriverObject->MajorFunction[IRP_MJ_CLOSE] = TiDispatchOpenClose;
760 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TiDispatchInternal;
761 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TiDispatch;
762
763 DriverObject->DriverUnload = TiUnload;
764
765 /* Open loopback adapter */
766 Status = LoopRegisterAdapter(NULL, NULL);
767 if (!NT_SUCCESS(Status)) {
768 TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status));
769 TiUnload(DriverObject);
770 return Status;
771 }
772
773 /* Register protocol with NDIS */
774 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
775 Status = LANRegisterProtocol(&strNdisDeviceName);
776 if (!NT_SUCCESS(Status)) {
777 TI_DbgPrint(MIN_TRACE,("Failed to register protocol with NDIS; status 0x%x\n", Status));
778 TiWriteErrorLog(
779 DriverObject,
780 EVENT_TRANSPORT_REGISTER_FAILED,
781 TI_ERROR_DRIVERENTRY,
782 Status,
783 NULL,
784 0,
785 NULL);
786 TiUnload(DriverObject);
787 return Status;
788 }
789
790 /* Start the periodic timer with an initial and periodic
791 relative expiration time of IP_TIMEOUT milliseconds */
792 DueTime.QuadPart = -(LONGLONG)IP_TIMEOUT * 10000;
793 KeSetTimerEx(&IPTimer, DueTime, IP_TIMEOUT, &IPTimeoutDpc);
794
795 TI_DbgPrint(MAX_TRACE, ("[TCPIP, DriverEntry] Finished\n"));
796
797
798 return STATUS_SUCCESS;
799 }
800
801 VOID NTAPI
802 IPAddInterface(
803 ULONG Unknown0,
804 ULONG Unknown1,
805 ULONG Unknown2,
806 ULONG Unknown3,
807 ULONG Unknown4)
808 {
809 UNIMPLEMENTED
810 }
811
812
813 VOID NTAPI
814 IPDelInterface(
815 ULONG Unknown0)
816 {
817 UNIMPLEMENTED
818 }
819
820
821 VOID NTAPI
822 LookupRoute(
823 ULONG Unknown0,
824 ULONG Unknown1)
825 {
826 UNIMPLEMENTED
827 }
828
829 /* EOF */