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