- Forgot to commit these for MSVC build...
[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 ChewShutdown();
623
624 /* Cancel timer */
625 KeCancelTimer(&IPTimer);
626
627 /* Unregister loopback adapter */
628 LoopUnregisterAdapter(NULL);
629
630 /* Unregister protocol with NDIS */
631 LANUnregisterProtocol();
632
633 /* Shutdown transport level protocol subsystems */
634 TCPShutdown();
635 UDPShutdown();
636 RawIPShutdown();
637
638 /* Shutdown network level protocol subsystem */
639 IPShutdown();
640
641 /* Shutdown the lan worker */
642 LANShutdown();
643
644 /* Free NDIS buffer descriptors */
645 if (GlobalBufferPool)
646 NdisFreeBufferPool(GlobalBufferPool);
647
648 /* Free NDIS packet descriptors */
649 if (GlobalPacketPool)
650 NdisFreePacketPool(GlobalPacketPool);
651
652 /* Release all device objects */
653
654 if (TCPDeviceObject)
655 IoDeleteDevice(TCPDeviceObject);
656
657 if (UDPDeviceObject)
658 IoDeleteDevice(UDPDeviceObject);
659
660 if (RawIPDeviceObject)
661 IoDeleteDevice(RawIPDeviceObject);
662
663 if (IPDeviceObject)
664 IoDeleteDevice(IPDeviceObject);
665
666 if (EntityList)
667 PoolFreeBuffer(EntityList);
668
669 TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
670 }
671
672 VOID STDCALL IPTimeoutDpcFn(
673 PKDPC Dpc,
674 PVOID DeferredContext,
675 PVOID SystemArgument1,
676 PVOID SystemArgument2)
677 /*
678 * FUNCTION: Timeout DPC
679 * ARGUMENTS:
680 * Dpc = Pointer to our DPC object
681 * DeferredContext = Pointer to context information (unused)
682 * SystemArgument1 = Unused
683 * SystemArgument2 = Unused
684 * NOTES:
685 * This routine is dispatched once in a while to do maintainance jobs
686 */
687 {
688 if( !IpWorkItemQueued ) {
689 ExQueueWorkItem( &IpWorkItem, CriticalWorkQueue );
690 IpWorkItemQueued = TRUE;
691 }
692 }
693
694 NTSTATUS
695 #ifndef _MSC_VER
696 STDCALL
697 #endif
698 DriverEntry(
699 PDRIVER_OBJECT DriverObject,
700 PUNICODE_STRING RegistryPath)
701 /*
702 * FUNCTION: Main driver entry point
703 * ARGUMENTS:
704 * DriverObject = Pointer to a driver object for this driver
705 * RegistryPath = Registry node for configuration parameters
706 * RETURNS:
707 * Status of driver initialization
708 */
709 {
710 NTSTATUS Status;
711 UNICODE_STRING strIpDeviceName = RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME);
712 UNICODE_STRING strRawDeviceName = RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME);
713 UNICODE_STRING strUdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
714 UNICODE_STRING strTcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
715 UNICODE_STRING strNdisDeviceName = RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME);
716 NDIS_STATUS NdisStatus;
717 LARGE_INTEGER DueTime;
718
719 TI_DbgPrint(MAX_TRACE, ("Called.\n"));
720
721 TrackingInit();
722 TrackTag(NDIS_BUFFER_TAG);
723 TrackTag(NDIS_PACKET_TAG);
724 TrackTag(FBSD_MALLOC);
725 TrackTag(EXALLOC_TAG);
726
727 /* TdiInitialize() ? */
728
729 /* FIXME: Create symbolic links in Win32 namespace */
730
731 /* Create IP device object */
732 Status = IoCreateDevice(DriverObject, 0, &strIpDeviceName,
733 FILE_DEVICE_NETWORK, 0, FALSE, &IPDeviceObject);
734 if (!NT_SUCCESS(Status)) {
735 TI_DbgPrint(MIN_TRACE, ("Failed to create IP device object. Status (0x%X).\n", Status));
736 return Status;
737 }
738
739 ChewInit( IPDeviceObject );
740
741 /* Create RawIP device object */
742 Status = IoCreateDevice(DriverObject, 0, &strRawDeviceName,
743 FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject);
744 if (!NT_SUCCESS(Status)) {
745 TI_DbgPrint(MIN_TRACE, ("Failed to create RawIP device object. Status (0x%X).\n", Status));
746 TiUnload(DriverObject);
747 return Status;
748 }
749
750 /* Create UDP device object */
751 Status = IoCreateDevice(DriverObject, 0, &strUdpDeviceName,
752 FILE_DEVICE_NETWORK, 0, FALSE, &UDPDeviceObject);
753 if (!NT_SUCCESS(Status)) {
754 TI_DbgPrint(MIN_TRACE, ("Failed to create UDP device object. Status (0x%X).\n", Status));
755 TiUnload(DriverObject);
756 return Status;
757 }
758
759 /* Create TCP device object */
760 Status = IoCreateDevice(DriverObject, 0, &strTcpDeviceName,
761 FILE_DEVICE_NETWORK, 0, FALSE, &TCPDeviceObject);
762 if (!NT_SUCCESS(Status)) {
763 TI_DbgPrint(MIN_TRACE, ("Failed to create TCP device object. Status (0x%X).\n", Status));
764 TiUnload(DriverObject);
765 return Status;
766 }
767
768 /* Setup network layer and transport layer entities */
769 KeInitializeSpinLock(&EntityListLock);
770 EntityList = ExAllocatePool(NonPagedPool, sizeof(TDIEntityID) * MAX_TDI_ENTITIES );
771 if (!NT_SUCCESS(Status)) {
772 TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
773 TiUnload(DriverObject);
774 return STATUS_INSUFFICIENT_RESOURCES;
775 }
776
777 EntityList[0].tei_entity = CL_NL_ENTITY;
778 EntityList[0].tei_instance = 0;
779 EntityList[0].context = 0;
780 EntityList[0].info_req = InfoNetworkLayerTdiQueryEx;
781 EntityList[0].info_set = InfoNetworkLayerTdiSetEx;
782 EntityList[1].tei_entity = CL_TL_ENTITY;
783 EntityList[1].tei_instance = 0;
784 EntityList[1].context = 0;
785 EntityList[1].info_req = InfoTransportLayerTdiQueryEx;
786 EntityList[1].info_set = InfoTransportLayerTdiSetEx;
787 EntityCount = 2;
788 EntityMax = MAX_TDI_ENTITIES;
789
790 /* Allocate NDIS packet descriptors */
791 NdisAllocatePacketPool(&NdisStatus, &GlobalPacketPool, 100, sizeof(PACKET_CONTEXT));
792 if (NdisStatus != NDIS_STATUS_SUCCESS) {
793 TiUnload(DriverObject);
794 return STATUS_INSUFFICIENT_RESOURCES;
795 }
796
797 /* Allocate NDIS buffer descriptors */
798 NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 100);
799 if (NdisStatus != NDIS_STATUS_SUCCESS) {
800 TiUnload(DriverObject);
801 return STATUS_INSUFFICIENT_RESOURCES;
802 }
803
804 /* Initialize address file list and protecting spin lock */
805 InitializeListHead(&AddressFileListHead);
806 KeInitializeSpinLock(&AddressFileListLock);
807
808 /* Initialize connection endpoint list and protecting spin lock */
809 InitializeListHead(&ConnectionEndpointListHead);
810 KeInitializeSpinLock(&ConnectionEndpointListLock);
811
812 /* Initialize interface list and protecting spin lock */
813 InitializeListHead(&InterfaceListHead);
814 KeInitializeSpinLock(&InterfaceListLock);
815
816 /* Initialize network level protocol subsystem */
817 IPStartup(RegistryPath);
818
819 /* Initialize transport level protocol subsystems */
820 RawIPStartup();
821 UDPStartup();
822 TCPStartup();
823
824 /* Initialize the lan worker */
825 LANStartup();
826
827 /* Register protocol with NDIS */
828 /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
829 Status = LANRegisterProtocol(&strNdisDeviceName);
830 if (!NT_SUCCESS(Status)) {
831 TI_DbgPrint(MIN_TRACE,("Failed to register protocol with NDIS; status 0x%x\n", Status));
832 TiWriteErrorLog(
833 DriverObject,
834 EVENT_TRANSPORT_REGISTER_FAILED,
835 TI_ERROR_DRIVERENTRY,
836 Status,
837 NULL,
838 0,
839 NULL);
840 TiUnload(DriverObject);
841 return Status;
842 }
843
844 /* Open loopback adapter */
845 if (!NT_SUCCESS(LoopRegisterAdapter(NULL, NULL))) {
846 TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status));
847 TiUnload(DriverObject);
848 return STATUS_INSUFFICIENT_RESOURCES;
849 }
850
851 /* Use direct I/O */
852 IPDeviceObject->Flags |= DO_DIRECT_IO;
853 RawIPDeviceObject->Flags |= DO_DIRECT_IO;
854 UDPDeviceObject->Flags |= DO_DIRECT_IO;
855 TCPDeviceObject->Flags |= DO_DIRECT_IO;
856
857 /* Initialize the driver object with this driver's entry points */
858 DriverObject->MajorFunction[IRP_MJ_CREATE] = TiDispatchOpenClose;
859 DriverObject->MajorFunction[IRP_MJ_CLOSE] = TiDispatchOpenClose;
860 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TiDispatchOpenClose;
861 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TiDispatchInternal;
862 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TiDispatch;
863
864 DriverObject->DriverUnload = TiUnload;
865
866 /* Initialize our periodic timer and its associated DPC object. When the
867 timer expires, the IPTimeout deferred procedure call (DPC) is queued */
868 ExInitializeWorkItem( &IpWorkItem, IPTimeout, NULL );
869 KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL);
870 KeInitializeTimer(&IPTimer);
871
872 /* Start the periodic timer with an initial and periodic
873 relative expiration time of IP_TIMEOUT milliseconds */
874 DueTime.QuadPart = -(LONGLONG)IP_TIMEOUT * 10000;
875 KeSetTimerEx(&IPTimer, DueTime, IP_TIMEOUT, &IPTimeoutDpc);
876
877 return STATUS_SUCCESS;
878 }
879
880
881 VOID
882 #ifndef _MSC_VER
883 STDCALL
884 #endif
885 IPAddInterface(
886 DWORD Unknown0,
887 DWORD Unknown1,
888 DWORD Unknown2,
889 DWORD Unknown3,
890 DWORD Unknown4)
891 {
892 UNIMPLEMENTED
893 }
894
895
896 VOID
897 #ifndef _MSC_VER
898 STDCALL
899 #endif
900 IPDelInterface(
901 DWORD Unknown0)
902 {
903 UNIMPLEMENTED
904 }
905
906
907 VOID
908 #ifndef _MSC_VER
909 STDCALL
910 #endif
911 LookupRoute(
912 DWORD Unknown0,
913 DWORD Unknown1)
914 {
915 UNIMPLEMENTED
916 }
917
918 /* EOF */