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