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