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