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