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