- Revert the oskit locking rewrite in trunk, it's better to test/debug it in the...
[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 PTRANSPORT_CONTEXT Context;
326
327 IRPRemember(Irp, __FILE__, __LINE__);
328
329 // DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
330
331 IrpSp = IoGetCurrentIrpStackLocation(Irp);
332
333 switch (IrpSp->MajorFunction) {
334 /* Open an address file, connection endpoint, or control connection */
335 case IRP_MJ_CREATE:
336 Status = TiCreateFileObject(DeviceObject, Irp);
337 break;
338
339 /* Close an address file, connection endpoint, or control connection */
340 case IRP_MJ_CLOSE:
341 Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
342 Status = TiCloseFileObject(DeviceObject, Irp);
343 break;
344
345 default:
346 Status = STATUS_INVALID_DEVICE_REQUEST;
347 }
348
349 //DbgPrint("Leaving. Status is (0x%X)\n", Status);
350
351 return IRPFinish( Irp, Status );
352 }
353
354
355 NTSTATUS NTAPI
356 TiDispatchInternal(
357 PDEVICE_OBJECT DeviceObject,
358 PIRP Irp)
359 /*
360 * FUNCTION: Internal IOCTL dispatch routine
361 * ARGUMENTS:
362 * DeviceObject = Pointer to a device object for this driver
363 * Irp = Pointer to a I/O request packet
364 * RETURNS:
365 * Status of the operation
366 */
367 {
368 NTSTATUS Status;
369 BOOLEAN Complete = TRUE;
370 PIO_STACK_LOCATION IrpSp;
371
372 IRPRemember(Irp, __FILE__, __LINE__);
373
374 IrpSp = IoGetCurrentIrpStackLocation(Irp);
375
376 TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
377 DeviceObject, Irp, IrpSp->MinorFunction));
378
379 Irp->IoStatus.Status = STATUS_SUCCESS;
380 Irp->IoStatus.Information = 0;
381
382 switch (IrpSp->MinorFunction) {
383 case TDI_RECEIVE:
384 Status = DispTdiReceive(Irp);
385 Complete = FALSE;
386 break;
387
388 case TDI_RECEIVE_DATAGRAM:
389 Status = DispTdiReceiveDatagram(Irp);
390 Complete = FALSE;
391 break;
392
393 case TDI_SEND:
394 Status = DispTdiSend(Irp);
395 Complete = FALSE; /* Completed in DispTdiSend */
396 break;
397
398 case TDI_SEND_DATAGRAM:
399 Status = DispTdiSendDatagram(Irp);
400 Complete = FALSE;
401 break;
402
403 case TDI_ACCEPT:
404 Status = DispTdiAccept(Irp);
405 break;
406
407 case TDI_LISTEN:
408 Status = DispTdiListen(Irp);
409 Complete = FALSE;
410 break;
411
412 case TDI_CONNECT:
413 Status = DispTdiConnect(Irp);
414 Complete = FALSE; /* Completed by the TCP event handler */
415 break;
416
417 case TDI_DISCONNECT:
418 Status = DispTdiDisconnect(Irp);
419 Complete = FALSE;
420 break;
421
422 case TDI_ASSOCIATE_ADDRESS:
423 Status = DispTdiAssociateAddress(Irp);
424 break;
425
426 case TDI_DISASSOCIATE_ADDRESS:
427 Status = DispTdiDisassociateAddress(Irp);
428 break;
429
430 case TDI_QUERY_INFORMATION:
431 Status = DispTdiQueryInformation(DeviceObject, Irp);
432 break;
433
434 case TDI_SET_INFORMATION:
435 Status = DispTdiSetInformation(Irp);
436 break;
437
438 case TDI_SET_EVENT_HANDLER:
439 Status = DispTdiSetEventHandler(Irp);
440 break;
441
442 case TDI_ACTION:
443 Status = STATUS_SUCCESS;
444 break;
445
446 /* An unsupported IOCTL code was submitted */
447 default:
448 Status = STATUS_INVALID_DEVICE_REQUEST;
449 }
450
451 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
452
453 if( Complete )
454 IRPFinish( Irp, Status );
455
456 return Status;
457 }
458
459
460 NTSTATUS NTAPI
461 TiDispatch(
462 PDEVICE_OBJECT DeviceObject,
463 PIRP Irp)
464 /*
465 * FUNCTION: Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
466 * ARGUMENTS:
467 * DeviceObject = Pointer to a device object for this driver
468 * Irp = Pointer to a I/O request packet
469 * RETURNS:
470 * Status of the operation
471 */
472 {
473 NTSTATUS Status;
474 PIO_STACK_LOCATION IrpSp;
475
476 IRPRemember(Irp, __FILE__, __LINE__);
477
478 IrpSp = IoGetCurrentIrpStackLocation(Irp);
479
480 TI_DbgPrint(DEBUG_IRP, ("Called. IRP is at (0x%X).\n", Irp));
481
482 Irp->IoStatus.Information = 0;
483
484 #if 0
485 Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp);
486 if (NT_SUCCESS(Status)) {
487 TiDispatchInternal(DeviceObject, Irp);
488 Status = STATUS_PENDING;
489 } else {
490 #else
491 if (TRUE) {
492 #endif
493 /* See if this request is TCP/IP specific */
494 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
495 case IOCTL_TCP_QUERY_INFORMATION_EX:
496 TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n"));
497 Status = DispTdiQueryInformationEx(Irp, IrpSp);
498 break;
499
500 case IOCTL_TCP_SET_INFORMATION_EX:
501 TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n"));
502 Status = DispTdiSetInformationEx(Irp, IrpSp);
503 break;
504
505 case IOCTL_SET_IP_ADDRESS:
506 TI_DbgPrint(MIN_TRACE, ("SET_IP_ADDRESS\n"));
507 Status = DispTdiSetIPAddress(Irp, IrpSp);
508 break;
509
510 case IOCTL_DELETE_IP_ADDRESS:
511 TI_DbgPrint(MIN_TRACE, ("DELETE_IP_ADDRESS\n"));
512 Status = DispTdiDeleteIPAddress(Irp, IrpSp);
513 break;
514
515 default:
516 TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
517 IrpSp->Parameters.DeviceIoControl.IoControlCode));
518 Status = STATUS_NOT_IMPLEMENTED;
519 break;
520 }
521 }
522
523 TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
524
525 return IRPFinish( Irp, Status );
526 }
527
528
529 VOID NTAPI TiUnload(
530 PDRIVER_OBJECT DriverObject)
531 /*
532 * FUNCTION: Unloads the driver
533 * ARGUMENTS:
534 * DriverObject = Pointer to driver object created by the system
535 */
536 {
537 #if DBG
538 KIRQL OldIrql;
539
540 TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
541 if (!IsListEmpty(&AddressFileListHead)) {
542 TI_DbgPrint(MIN_TRACE, ("Open address file objects exists.\n"));
543 }
544 TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
545 #endif
546 ChewShutdown();
547
548 /* Cancel timer */
549 KeCancelTimer(&IPTimer);
550
551 /* Unregister loopback adapter */
552 LoopUnregisterAdapter(NULL);
553
554 /* Unregister protocol with NDIS */
555 LANUnregisterProtocol();
556
557 /* Shutdown transport level protocol subsystems */
558 TCPShutdown();
559 UDPShutdown();
560 RawIPShutdown();
561 ICMPShutdown();
562
563 /* Shutdown network level protocol subsystem */
564 IPShutdown();
565
566 /* Free NDIS buffer descriptors */
567 if (GlobalBufferPool)
568 NdisFreeBufferPool(GlobalBufferPool);
569
570 /* Free NDIS packet descriptors */
571 if (GlobalPacketPool)
572 NdisFreePacketPool(GlobalPacketPool);
573
574 /* Release all device objects */
575
576 if (TCPDeviceObject)
577 IoDeleteDevice(TCPDeviceObject);
578
579 if (UDPDeviceObject)
580 IoDeleteDevice(UDPDeviceObject);
581
582 if (RawIPDeviceObject)
583 IoDeleteDevice(RawIPDeviceObject);
584
585 if (IPDeviceObject)
586 IoDeleteDevice(IPDeviceObject);
587
588 if (EntityList)
589 exFreePool(EntityList);
590
591 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
592 }
593
594 VOID NTAPI IPTimeoutDpcFn(
595 PKDPC Dpc,
596 PVOID DeferredContext,
597 PVOID SystemArgument1,
598 PVOID SystemArgument2)
599 /*
600 * FUNCTION: Timeout DPC
601 * ARGUMENTS:
602 * Dpc = Pointer to our DPC object
603 * DeferredContext = Pointer to context information (unused)
604 * SystemArgument1 = Unused
605 * SystemArgument2 = Unused
606 * NOTES:
607 * This routine is dispatched once in a while to do maintainance jobs
608 */
609 {
610 if( !IpWorkItemQueued ) {
611 ExQueueWorkItem( &IpWorkItem, DelayedWorkQueue );
612 IpWorkItemQueued = TRUE;
613 }
614 }
615
616 NTSTATUS NTAPI
617 DriverEntry(
618 PDRIVER_OBJECT DriverObject,
619 PUNICODE_STRING RegistryPath)
620 /*
621 * FUNCTION: Main driver entry point
622 * ARGUMENTS:
623 * DriverObject = Pointer to a driver object for this driver
624 * RegistryPath = Registry node for configuration parameters
625 * RETURNS:
626 * Status of driver initialization
627 */
628 {
629 NTSTATUS Status;
630 UNICODE_STRING strIpDeviceName = RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME);
631 UNICODE_STRING strRawDeviceName = RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME);
632 UNICODE_STRING strUdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
633 UNICODE_STRING strTcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
634 UNICODE_STRING strNdisDeviceName = RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME);
635 NDIS_STATUS NdisStatus;
636 LARGE_INTEGER DueTime;
637
638 TI_DbgPrint(MAX_TRACE, ("Called.\n"));
639
640 TrackingInit();
641
642 /* TdiInitialize() ? */
643
644 /* FIXME: Create symbolic links in Win32 namespace */
645
646 /* Create IP device object */
647 Status = IoCreateDevice(DriverObject, 0, &strIpDeviceName,
648 FILE_DEVICE_NETWORK, 0, FALSE, &IPDeviceObject);
649 if (!NT_SUCCESS(Status)) {
650 TI_DbgPrint(MIN_TRACE, ("Failed to create IP device object. Status (0x%X).\n", Status));
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 ChewShutdown();
662 IoDeleteDevice(IPDeviceObject);
663 return Status;
664 }
665
666 /* Create UDP device object */
667 Status = IoCreateDevice(DriverObject, 0, &strUdpDeviceName,
668 FILE_DEVICE_NETWORK, 0, FALSE, &UDPDeviceObject);
669 if (!NT_SUCCESS(Status)) {
670 TI_DbgPrint(MIN_TRACE, ("Failed to create UDP device object. Status (0x%X).\n", Status));
671 ChewShutdown();
672 IoDeleteDevice(IPDeviceObject);
673 IoDeleteDevice(RawIPDeviceObject);
674 return Status;
675 }
676
677 /* Create TCP device object */
678 Status = IoCreateDevice(DriverObject, 0, &strTcpDeviceName,
679 FILE_DEVICE_NETWORK, 0, FALSE, &TCPDeviceObject);
680 if (!NT_SUCCESS(Status)) {
681 TI_DbgPrint(MIN_TRACE, ("Failed to create TCP device object. Status (0x%X).\n", Status));
682 ChewShutdown();
683 IoDeleteDevice(IPDeviceObject);
684 IoDeleteDevice(RawIPDeviceObject);
685 IoDeleteDevice(UDPDeviceObject);
686 return Status;
687 }
688
689 /* Setup network layer and transport layer entities */
690 KeInitializeSpinLock(&EntityListLock);
691 EntityList = exAllocatePool(NonPagedPool, sizeof(TDIEntityID) * MAX_TDI_ENTITIES );
692 if (!EntityList) {
693 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
694 ChewShutdown();
695 IoDeleteDevice(IPDeviceObject);
696 IoDeleteDevice(RawIPDeviceObject);
697 IoDeleteDevice(UDPDeviceObject);
698 IoDeleteDevice(TCPDeviceObject);
699 return STATUS_INSUFFICIENT_RESOURCES;
700 }
701
702 EntityCount = 0;
703 EntityMax = MAX_TDI_ENTITIES;
704
705 /* Allocate NDIS packet descriptors */
706 NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT));
707 if (NdisStatus != NDIS_STATUS_SUCCESS) {
708 ChewShutdown();
709 IoDeleteDevice(IPDeviceObject);
710 IoDeleteDevice(RawIPDeviceObject);
711 IoDeleteDevice(UDPDeviceObject);
712 IoDeleteDevice(TCPDeviceObject);
713 exFreePool(EntityList);
714 return STATUS_INSUFFICIENT_RESOURCES;
715 }
716
717 /* Allocate NDIS buffer descriptors */
718 NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 100);
719 if (NdisStatus != NDIS_STATUS_SUCCESS) {
720 ChewShutdown();
721 IoDeleteDevice(IPDeviceObject);
722 IoDeleteDevice(RawIPDeviceObject);
723 IoDeleteDevice(UDPDeviceObject);
724 IoDeleteDevice(TCPDeviceObject);
725 exFreePool(EntityList);
726 NdisFreePacketPool(GlobalPacketPool);
727 return STATUS_INSUFFICIENT_RESOURCES;
728 }
729
730 /* Initialize address file list and protecting spin lock */
731 InitializeListHead(&AddressFileListHead);
732 KeInitializeSpinLock(&AddressFileListLock);
733
734 /* Initialize connection endpoint list and protecting spin lock */
735 InitializeListHead(&ConnectionEndpointListHead);
736 KeInitializeSpinLock(&ConnectionEndpointListLock);
737
738 /* Initialize interface list and protecting spin lock */
739 InitializeListHead(&InterfaceListHead);
740 KeInitializeSpinLock(&InterfaceListLock);
741
742 /* Initialize network level protocol subsystem */
743 IPStartup(RegistryPath);
744
745 /* Initialize transport level protocol subsystems */
746 Status = RawIPStartup();
747 if( !NT_SUCCESS(Status) ) {
748 IPShutdown();
749 ChewShutdown();
750 IoDeleteDevice(IPDeviceObject);
751 IoDeleteDevice(RawIPDeviceObject);
752 IoDeleteDevice(UDPDeviceObject);
753 IoDeleteDevice(TCPDeviceObject);
754 exFreePool(EntityList);
755 NdisFreePacketPool(GlobalPacketPool);
756 NdisFreeBufferPool(GlobalBufferPool);
757 return Status;
758 }
759
760 Status = UDPStartup();
761 if( !NT_SUCCESS(Status) ) {
762 RawIPShutdown();
763 IPShutdown();
764 ChewShutdown();
765 IoDeleteDevice(IPDeviceObject);
766 IoDeleteDevice(RawIPDeviceObject);
767 IoDeleteDevice(UDPDeviceObject);
768 IoDeleteDevice(TCPDeviceObject);
769 exFreePool(EntityList);
770 NdisFreePacketPool(GlobalPacketPool);
771 NdisFreeBufferPool(GlobalBufferPool);
772 return Status;
773 }
774
775 Status = TCPStartup();
776 if( !NT_SUCCESS(Status) ) {
777 UDPShutdown();
778 RawIPShutdown();
779 IPShutdown();
780 ChewShutdown();
781 IoDeleteDevice(IPDeviceObject);
782 IoDeleteDevice(RawIPDeviceObject);
783 IoDeleteDevice(UDPDeviceObject);
784 IoDeleteDevice(TCPDeviceObject);
785 exFreePool(EntityList);
786 NdisFreePacketPool(GlobalPacketPool);
787 NdisFreeBufferPool(GlobalBufferPool);
788 return Status;
789 }
790
791 Status = ICMPStartup();
792 if( !NT_SUCCESS(Status) ) {
793 TCPShutdown();
794 UDPShutdown();
795 RawIPShutdown();
796 IPShutdown();
797 ChewShutdown();
798 IoDeleteDevice(IPDeviceObject);
799 IoDeleteDevice(RawIPDeviceObject);
800 IoDeleteDevice(UDPDeviceObject);
801 IoDeleteDevice(TCPDeviceObject);
802 exFreePool(EntityList);
803 NdisFreePacketPool(GlobalPacketPool);
804 NdisFreeBufferPool(GlobalBufferPool);
805 return Status;
806 }
807
808 /* Use direct I/O */
809 IPDeviceObject->Flags |= DO_DIRECT_IO;
810 RawIPDeviceObject->Flags |= DO_DIRECT_IO;
811 UDPDeviceObject->Flags |= DO_DIRECT_IO;
812 TCPDeviceObject->Flags |= DO_DIRECT_IO;
813
814 /* Initialize the driver object with this driver's entry points */
815 DriverObject->MajorFunction[IRP_MJ_CREATE] = TiDispatchOpenClose;
816 DriverObject->MajorFunction[IRP_MJ_CLOSE] = TiDispatchOpenClose;
817 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TiDispatchInternal;
818 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TiDispatch;
819
820 DriverObject->DriverUnload = TiUnload;
821
822 /* Initialize our periodic timer and its associated DPC object. When the
823 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
824 ExInitializeWorkItem( &IpWorkItem, IPTimeout, NULL );
825 KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL);
826 KeInitializeTimer(&IPTimer);
827
828 /* Start the periodic timer with an initial and periodic
829 relative expiration time of IP_TIMEOUT milliseconds */
830 DueTime.QuadPart = -(LONGLONG)IP_TIMEOUT * 10000;
831 KeSetTimerEx(&IPTimer, DueTime, IP_TIMEOUT, &IPTimeoutDpc);
832
833 /* Open loopback adapter */
834 Status = LoopRegisterAdapter(NULL, NULL);
835 if (!NT_SUCCESS(Status)) {
836 TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status));
837 TCPShutdown();
838 UDPShutdown();
839 RawIPShutdown();
840 IPShutdown();
841 ChewShutdown();
842 IoDeleteDevice(IPDeviceObject);
843 IoDeleteDevice(RawIPDeviceObject);
844 IoDeleteDevice(UDPDeviceObject);
845 IoDeleteDevice(TCPDeviceObject);
846 exFreePool(EntityList);
847 NdisFreePacketPool(GlobalPacketPool);
848 NdisFreeBufferPool(GlobalBufferPool);
849 return Status;
850 }
851
852 /* Register protocol with NDIS */
853 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
854 Status = LANRegisterProtocol(&strNdisDeviceName);
855 if (!NT_SUCCESS(Status)) {
856 TI_DbgPrint(MIN_TRACE,("Failed to register protocol with NDIS; status 0x%x\n", Status));
857 TiWriteErrorLog(
858 DriverObject,
859 EVENT_TRANSPORT_REGISTER_FAILED,
860 TI_ERROR_DRIVERENTRY,
861 Status,
862 NULL,
863 0,
864 NULL);
865 TCPShutdown();
866 UDPShutdown();
867 RawIPShutdown();
868 IPShutdown();
869 ChewShutdown();
870 IoDeleteDevice(IPDeviceObject);
871 IoDeleteDevice(RawIPDeviceObject);
872 IoDeleteDevice(UDPDeviceObject);
873 IoDeleteDevice(TCPDeviceObject);
874 exFreePool(EntityList);
875 NdisFreePacketPool(GlobalPacketPool);
876 NdisFreeBufferPool(GlobalBufferPool);
877 return Status;
878 }
879
880 return STATUS_SUCCESS;
881 }
882
883
884 VOID NTAPI
885 IPAddInterface(
886 ULONG Unknown0,
887 ULONG Unknown1,
888 ULONG Unknown2,
889 ULONG Unknown3,
890 ULONG Unknown4)
891 {
892 UNIMPLEMENTED
893 }
894
895
896 VOID NTAPI
897 IPDelInterface(
898 ULONG Unknown0)
899 {
900 UNIMPLEMENTED
901 }
902
903
904 VOID NTAPI
905 LookupRoute(
906 ULONG Unknown0,
907 ULONG Unknown1)
908 {
909 UNIMPLEMENTED
910 }
911
912 /* EOF */