xref: /reactos/drivers/network/tcpip/tcpip/main.c (revision 95c104f2)
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 
11 #include "precomp.h"
12 
13 #include <ntifs.h>
14 #include <ndk/rtlfuncs.h>
15 #include <ndk/obfuncs.h>
16 
17 #include <dispatch.h>
18 #include <fileobjs.h>
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 
TiWriteErrorLog(PDRIVER_OBJECT DriverContext,NTSTATUS ErrorCode,ULONG UniqueErrorValue,NTSTATUS FinalStatus,PWSTR String,ULONG DumpDataCount,PULONG DumpData)36 VOID TiWriteErrorLog(
37     PDRIVER_OBJECT DriverContext,
38     NTSTATUS ErrorCode,
39     ULONG UniqueErrorValue,
40     NTSTATUS FinalStatus,
41     PWSTR String,
42     ULONG DumpDataCount,
43     PULONG DumpData)
44 /*
45  * FUNCTION: Writes an error log entry
46  * ARGUMENTS:
47  *     DriverContext    = Pointer to the driver or device object
48  *     ErrorCode        = An error code to put in the log entry
49  *     UniqueErrorValue = UniqueErrorValue in the error log packet
50  *     FinalStatus      = FinalStatus in the error log packet
51  *     String           = If not NULL, a pointer to a string to put in log
52  *                        entry
53  *     DumpDataCount    = Number of ULONGs of dump data
54  *     DumpData         = Pointer to dump data for the log entry
55  */
56 {
57     PIO_ERROR_LOG_PACKET LogEntry;
58     UCHAR EntrySize;
59     ULONG StringSize;
60     PUCHAR pString;
61     static WCHAR DriverName[] = L"TCP/IP";
62 
63     EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
64         (DumpDataCount * sizeof(ULONG)) + sizeof(DriverName);
65 
66     if (String) {
67         StringSize = (wcslen(String) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
68         EntrySize += (UCHAR)StringSize;
69     }
70 
71     /* Fail if the required error log entry is too large */
72     if (EntrySize > ERROR_LOG_MAXIMUM_SIZE)
73         return;
74 
75     LogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DriverContext, EntrySize);
76     if (!LogEntry)
77         return;
78 
79     LogEntry->MajorFunctionCode = -1;
80     LogEntry->RetryCount        = -1;
81     LogEntry->DumpDataSize      = (USHORT)(DumpDataCount * sizeof(ULONG));
82     LogEntry->NumberOfStrings   = (String == NULL) ? 1 : 2;
83     LogEntry->StringOffset      = sizeof(IO_ERROR_LOG_PACKET) + (DumpDataCount * sizeof(ULONG));
84     LogEntry->EventCategory     = 0;
85     LogEntry->ErrorCode         = ErrorCode;
86     LogEntry->UniqueErrorValue  = UniqueErrorValue;
87     LogEntry->FinalStatus       = FinalStatus;
88     LogEntry->SequenceNumber    = -1;
89     LogEntry->IoControlCode     = 0;
90 
91     if (DumpDataCount)
92         RtlCopyMemory(LogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
93 
94     pString = ((PUCHAR)LogEntry) + LogEntry->StringOffset;
95     RtlCopyMemory(pString, DriverName, sizeof(DriverName));
96     pString += sizeof(DriverName);
97 
98     if (String)
99         RtlCopyMemory(pString, String, StringSize);
100 
101     IoWriteErrorLogEntry(LogEntry);
102 }
103 
104 /*
105  * FUNCTION: Creates a file object
106  * ARGUMENTS:
107  *     DeviceObject = Pointer to a device object for this driver
108  *     Irp          = Pointer to a I/O request packet
109  * RETURNS:
110  *     Status of the operation
111  */
112 
TiCreateFileObject(PDEVICE_OBJECT DeviceObject,PIRP Irp)113 NTSTATUS TiCreateFileObject(
114     PDEVICE_OBJECT DeviceObject,
115     PIRP Irp)
116 {
117     PFILE_FULL_EA_INFORMATION EaInfo;
118     PTRANSPORT_CONTEXT Context;
119     PIO_STACK_LOCATION IrpSp;
120     PTA_IP_ADDRESS Address;
121     TDI_REQUEST Request;
122     PVOID ClientContext;
123     NTSTATUS Status;
124     ULONG Protocol;
125     BOOLEAN Shared;
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 
131     /* Parameter check */
132     /* No EA information means that we're opening for SET/QUERY_INFORMATION
133     * style calls. */
134 
135     /* Allocate resources here. We release them again if something failed */
136     Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSPORT_CONTEXT),
137                                     TRANS_CONTEXT_TAG);
138     if (!Context)
139     {
140         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
141         return STATUS_INSUFFICIENT_RESOURCES;
142     }
143 
144     Context->CancelIrps = FALSE;
145 
146     IrpSp = IoGetCurrentIrpStackLocation(Irp);
147     IrpSp->FileObject->FsContext = Context;
148     Request.RequestContext       = Irp;
149 
150     /* Branch to the right handler */
151     if (EaInfo &&
152         (EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
153         (RtlCompareMemory(&EaInfo->EaName, TdiTransportAddress,
154         TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH))
155     {
156         /* This is a request to open an address */
157 
158 
159         /* XXX This should probably be done in IoCreateFile() */
160         /* Parameter checks */
161 
162         Address = (PTA_IP_ADDRESS)(EaInfo->EaName + EaInfo->EaNameLength + 1); //0-term
163 
164         if ((EaInfo->EaValueLength < sizeof(TA_IP_ADDRESS)) ||
165             (Address->TAAddressCount != 1) ||
166             (Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) ||
167             (Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP))
168         {
169             TI_DbgPrint(MIN_TRACE, ("Parameters are invalid:\n"));
170             TI_DbgPrint(MIN_TRACE, ("AddressCount: %d\n", Address->TAAddressCount));
171             if( Address->TAAddressCount == 1 )
172             {
173                 TI_DbgPrint(MIN_TRACE, ("AddressLength: %u\n",
174                             Address->Address[0].AddressLength));
175                 TI_DbgPrint(MIN_TRACE, ("AddressType: %u\n",
176                             Address->Address[0].AddressType));
177             }
178 
179             ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
180             return STATUS_INVALID_PARAMETER;
181         }
182 
183         /* Open address file object */
184 
185         /* Protocol depends on device object so find the protocol */
186         if (DeviceObject == TCPDeviceObject)
187             Protocol = IPPROTO_TCP;
188         else if (DeviceObject == UDPDeviceObject)
189             Protocol = IPPROTO_UDP;
190         else if (DeviceObject == IPDeviceObject)
191             Protocol = IPPROTO_RAW;
192         else if (DeviceObject == RawIPDeviceObject)
193         {
194             Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
195             if (!NT_SUCCESS(Status))
196             {
197                 TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
198                 ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
199                 return STATUS_INVALID_PARAMETER;
200             }
201         }
202         else
203         {
204             TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
205             ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
206             return STATUS_INVALID_PARAMETER;
207         }
208 
209         Shared = (IrpSp->Parameters.Create.ShareAccess != 0);
210 
211         Status = FileOpenAddress(&Request, Address, Protocol, Shared, NULL);
212         if (NT_SUCCESS(Status))
213         {
214             IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
215             Context->Handle.AddressHandle = Request.Handle.AddressHandle;
216         }
217 
218     }
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     {
226         /* This is a request to open a connection endpoint */
227 
228         /* Parameter checks */
229 
230         if (EaInfo->EaValueLength < sizeof(PVOID))
231         {
232             TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
233             ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
234             return STATUS_INVALID_PARAMETER;
235         }
236 
237         /* Can only do connection oriented communication using TCP */
238 
239         if (DeviceObject != TCPDeviceObject)
240         {
241             TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
242             ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
243             return STATUS_INVALID_PARAMETER;
244         }
245 
246         ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength));
247 
248         /* Open connection endpoint file object */
249 
250         Status = FileOpenConnection(&Request, ClientContext);
251         if (NT_SUCCESS(Status))
252         {
253             IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
254             Context->Handle.ConnectionContext = Request.Handle.ConnectionContext;
255         }
256     }
257     else
258     {
259         /* This is a request to open a control connection */
260         Status = FileOpenControlChannel(&Request);
261         if (NT_SUCCESS(Status))
262         {
263             IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
264             Context->Handle.ControlChannel = Request.Handle.ControlChannel;
265         }
266     }
267 
268     if (!NT_SUCCESS(Status))
269         ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
270 
271     TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
272 
273     Irp->IoStatus.Status = Status;
274     return Status;
275 }
276 
277 
278 /*
279  * FUNCTION: Releases resources used by a file object
280  * ARGUMENTS:
281  *     DeviceObject = Pointer to a device object for this driver
282  *     Irp          = Pointer to a I/O request packet
283  * RETURNS:
284  *     Status of the operation
285  * NOTES:
286  *     This function does not pend
287  */
TiCloseFileObject(PDEVICE_OBJECT DeviceObject,PIRP Irp)288 NTSTATUS TiCloseFileObject(
289     PDEVICE_OBJECT DeviceObject,
290     PIRP Irp)
291 {
292     PIO_STACK_LOCATION IrpSp;
293     PTRANSPORT_CONTEXT Context;
294     TDI_REQUEST Request;
295     NTSTATUS Status;
296 
297     IrpSp   = IoGetCurrentIrpStackLocation(Irp);
298     Context = IrpSp->FileObject->FsContext;
299     if (!Context)
300     {
301         TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
302         return STATUS_INVALID_PARAMETER;
303     }
304 
305     switch ((ULONG_PTR)IrpSp->FileObject->FsContext2)
306     {
307         case TDI_TRANSPORT_ADDRESS_FILE:
308             Request.Handle.AddressHandle = Context->Handle.AddressHandle;
309             Status = FileCloseAddress(&Request);
310             break;
311 
312         case TDI_CONNECTION_FILE:
313             Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
314             Status = FileCloseConnection(&Request);
315             break;
316 
317         case TDI_CONTROL_CHANNEL_FILE:
318             Request.Handle.ControlChannel = Context->Handle.ControlChannel;
319             Status = FileCloseControlChannel(&Request);
320             break;
321 
322         default:
323             Status = STATUS_INVALID_PARAMETER;
324             break;
325     }
326 
327     if (NT_SUCCESS(Status))
328         ExFreePoolWithTag(Context, TRANS_CONTEXT_TAG);
329 
330     Irp->IoStatus.Status = Status;
331 
332     return Irp->IoStatus.Status;
333 }
334 
335 
336 NTSTATUS NTAPI
TiDispatchOpenClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)337 TiDispatchOpenClose(
338     IN PDEVICE_OBJECT DeviceObject,
339     IN PIRP Irp)
340 /*
341  * FUNCTION: Main dispath routine
342  * ARGUMENTS:
343  *     DeviceObject = Pointer to a device object for this driver
344  *     Irp          = Pointer to a I/O request packet
345  * RETURNS:
346  *     Status of the operation
347  */
348 {
349     PIO_STACK_LOCATION IrpSp;
350     NTSTATUS Status;
351 
352 //  DbgPrint("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp);
353 
354     IrpSp = IoGetCurrentIrpStackLocation(Irp);
355 
356     switch (IrpSp->MajorFunction) {
357     /* Open an address file, connection endpoint, or control connection */
358     case IRP_MJ_CREATE:
359         Status = TiCreateFileObject(DeviceObject, Irp);
360         break;
361 
362     /* Close an address file, connection endpoint, or control connection */
363     case IRP_MJ_CLOSE:
364         Status = TiCloseFileObject(DeviceObject, Irp);
365         break;
366 
367      default:
368         Status = STATUS_INVALID_DEVICE_REQUEST;
369     }
370 
371     //DbgPrint("Leaving. Status is (0x%X)\n", Status);
372 
373     return IRPFinish( Irp, Status );
374 }
375 
376 
377 NTSTATUS NTAPI
TiDispatchInternal(PDEVICE_OBJECT DeviceObject,PIRP Irp)378 TiDispatchInternal(
379     PDEVICE_OBJECT DeviceObject,
380     PIRP Irp)
381 /*
382  * FUNCTION: Internal IOCTL dispatch routine
383  * ARGUMENTS:
384  *     DeviceObject = Pointer to a device object for this driver
385  *     Irp          = Pointer to a I/O request packet
386  * RETURNS:
387  *     Status of the operation
388  */
389 {
390     NTSTATUS Status;
391     BOOLEAN Complete = TRUE;
392     PIO_STACK_LOCATION IrpSp;
393 
394     IrpSp = IoGetCurrentIrpStackLocation(Irp);
395 
396     TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
397         DeviceObject, Irp, IrpSp->MinorFunction));
398 
399     Irp->IoStatus.Status      = STATUS_SUCCESS;
400     Irp->IoStatus.Information = 0;
401 
402     switch (IrpSp->MinorFunction) {
403     case TDI_RECEIVE:
404         Status = DispTdiReceive(Irp);
405         Complete = FALSE;
406         break;
407 
408     case TDI_RECEIVE_DATAGRAM:
409         Status = DispTdiReceiveDatagram(Irp);
410         Complete = FALSE;
411         break;
412 
413     case TDI_SEND:
414         Status = DispTdiSend(Irp);
415         Complete = FALSE; /* Completed in DispTdiSend */
416         break;
417 
418     case TDI_SEND_DATAGRAM:
419         Status = DispTdiSendDatagram(Irp);
420         Complete = FALSE;
421         break;
422 
423   case TDI_ACCEPT:
424     Status = DispTdiAccept(Irp);
425     break;
426 
427     case TDI_LISTEN:
428         Status = DispTdiListen(Irp);
429         Complete = FALSE;
430         break;
431 
432     case TDI_CONNECT:
433         Status = DispTdiConnect(Irp);
434         Complete = FALSE; /* Completed by the TCP event handler */
435         break;
436 
437     case TDI_DISCONNECT:
438         Status = DispTdiDisconnect(Irp);
439         Complete = FALSE;
440         break;
441 
442     case TDI_ASSOCIATE_ADDRESS:
443         Status = DispTdiAssociateAddress(Irp);
444         break;
445 
446     case TDI_DISASSOCIATE_ADDRESS:
447         Status = DispTdiDisassociateAddress(Irp);
448         break;
449 
450     case TDI_QUERY_INFORMATION:
451         Status = DispTdiQueryInformation(DeviceObject, Irp);
452         break;
453 
454     case TDI_SET_INFORMATION:
455         Status = DispTdiSetInformation(Irp);
456         break;
457 
458     case TDI_SET_EVENT_HANDLER:
459         Status = DispTdiSetEventHandler(Irp);
460         break;
461 
462     case TDI_ACTION:
463         Status = STATUS_SUCCESS;
464         break;
465 
466     /* An unsupported IOCTL code was submitted */
467     default:
468         Status = STATUS_INVALID_DEVICE_REQUEST;
469     }
470 
471     TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatchInternal] Leaving. Status = (0x%X).\n", Status));
472 
473     if( Complete )
474         IRPFinish( Irp, Status );
475 
476     return Status;
477 }
478 
479 
480 /**
481  * @brief Dispatch routine for IRP_MJ_DEVICE_CONTROL requests
482  *
483  * @param[in] DeviceObject
484  *   Pointer to a device object for this driver
485  * @param[in] Irp
486  *   Pointer to a I/O request packet
487  *
488  * @return
489  *   Status of the operation
490  */
491 NTSTATUS NTAPI
TiDispatch(PDEVICE_OBJECT DeviceObject,PIRP Irp)492 TiDispatch(
493     PDEVICE_OBJECT DeviceObject,
494     PIRP Irp)
495 {
496     NTSTATUS Status;
497     PIO_STACK_LOCATION IrpSp;
498 
499     IrpSp = IoGetCurrentIrpStackLocation(Irp);
500 
501     TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Called. IRP is at (0x%X).\n", Irp));
502 
503     Irp->IoStatus.Information = 0;
504 
505 #if 0
506     Status = TdiMapUserRequest(DeviceObject, Irp, IrpSp);
507     if (NT_SUCCESS(Status))
508     {
509         TiDispatchInternal(DeviceObject, Irp);
510         Status = STATUS_PENDING;
511     }
512     else
513     {
514 #else
515     if (TRUE) {
516 #endif
517         /* See if this request is TCP/IP specific */
518         switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
519         {
520             case IOCTL_TCP_QUERY_INFORMATION_EX:
521                 TI_DbgPrint(MIN_TRACE, ("TCP_QUERY_INFORMATION_EX\n"));
522                 Status = DispTdiQueryInformationEx(Irp, IrpSp);
523                 break;
524 
525             case IOCTL_TCP_SET_INFORMATION_EX:
526                 TI_DbgPrint(MIN_TRACE, ("TCP_SET_INFORMATION_EX\n"));
527                 Status = DispTdiSetInformationEx(Irp, IrpSp);
528                 break;
529 
530             case IOCTL_SET_IP_ADDRESS:
531                 TI_DbgPrint(MIN_TRACE, ("SET_IP_ADDRESS\n"));
532                 Status = DispTdiSetIPAddress(Irp, IrpSp);
533                 break;
534 
535             case IOCTL_DELETE_IP_ADDRESS:
536                 TI_DbgPrint(MIN_TRACE, ("DELETE_IP_ADDRESS\n"));
537                 Status = DispTdiDeleteIPAddress(Irp, IrpSp);
538                 break;
539 
540             case IOCTL_QUERY_IP_HW_ADDRESS:
541                 TI_DbgPrint(MIN_TRACE, ("QUERY_IP_HW_ADDRESS\n"));
542                 Status = DispTdiQueryIpHwAddress(DeviceObject, Irp, IrpSp);
543                 break;
544 
545             case IOCTL_ICMP_ECHO_REQUEST:
546                 TI_DbgPrint(MIN_TRACE, ("ICMP_ECHO_REQUEST\n"));
547                 Status = DispEchoRequest(DeviceObject, Irp, IrpSp);
548                 break;
549 
550             default:
551                 TI_DbgPrint(MIN_TRACE, ("Unknown IOCTL 0x%X\n",
552                     IrpSp->Parameters.DeviceIoControl.IoControlCode));
553                 Status = STATUS_NOT_IMPLEMENTED;
554                 break;
555         }
556     }
557 
558     TI_DbgPrint(DEBUG_IRP, ("[TCPIP, TiDispatch] Leaving. Status = (0x%X).\n", Status));
559 
560     return IRPFinish(Irp, Status);
561 }
562 
563 static
564 NTSTATUS TiCreateSecurityDescriptor(
565     _Out_ PSECURITY_DESCRIPTOR *SecurityDescriptor)
566 {
567     NTSTATUS Status;
568     SECURITY_DESCRIPTOR AbsSD;
569     ULONG DaclSize, RelSDSize = 0;
570     PSECURITY_DESCRIPTOR RelSD = NULL;
571     PACL Dacl = NULL;
572 
573     /* Setup a SD */
574     Status = RtlCreateSecurityDescriptor(&AbsSD,
575                                          SECURITY_DESCRIPTOR_REVISION);
576     if (!NT_SUCCESS(Status))
577     {
578         TI_DbgPrint(MIN_TRACE, ("Failed to create the absolute SD (0x%X)\n", Status));
579         goto Quit;
580     }
581 
582     /* Setup a DACL */
583     DaclSize = sizeof(ACL) +
584                sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(SeExports->SeLocalSystemSid) +
585                sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(SeExports->SeAliasAdminsSid) +
586                sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(SeExports->SeNetworkServiceSid);
587     Dacl = ExAllocatePoolWithTag(PagedPool,
588                                  DaclSize,
589                                  DEVICE_OBJ_SECURITY_TAG);
590     if (Dacl == NULL)
591     {
592         TI_DbgPrint(MIN_TRACE, ("Failed to allocate buffer heap for a DACL\n"));
593         Status = STATUS_INSUFFICIENT_RESOURCES;
594         goto Quit;
595     }
596 
597     Status = RtlCreateAcl(Dacl,
598                           DaclSize,
599                           ACL_REVISION);
600     if (!NT_SUCCESS(Status))
601     {
602         TI_DbgPrint(MIN_TRACE, ("Failed to create a DACL (0x%X)\n", Status));
603         goto Quit;
604     }
605 
606     /* Setup access */
607     Status = RtlAddAccessAllowedAce(Dacl,
608                                     ACL_REVISION,
609                                     GENERIC_ALL,
610                                     SeExports->SeLocalSystemSid);
611     if (!NT_SUCCESS(Status))
612     {
613         TI_DbgPrint(MIN_TRACE, ("Failed to add access allowed ACE for System SID (0x%X)\n", Status));
614         goto Quit;
615     }
616 
617     Status = RtlAddAccessAllowedAce(Dacl,
618                                     ACL_REVISION,
619                                     GENERIC_ALL,
620                                     SeExports->SeAliasAdminsSid);
621     if (!NT_SUCCESS(Status))
622     {
623         TI_DbgPrint(MIN_TRACE, ("Failed to add access allowed ACE for Admins SID (0x%X)\n", Status));
624         goto Quit;
625     }
626 
627     Status = RtlAddAccessAllowedAce(Dacl,
628                                     ACL_REVISION,
629                                     GENERIC_ALL,
630                                     SeExports->SeNetworkServiceSid);
631     if (!NT_SUCCESS(Status))
632     {
633         TI_DbgPrint(MIN_TRACE, ("Failed to add access allowed ACE for Network Service SID (0x%X)\n", Status));
634         goto Quit;
635     }
636 
637     /* Assign security data to SD */
638     Status = RtlSetDaclSecurityDescriptor(&AbsSD,
639                                           TRUE,
640                                           Dacl,
641                                           FALSE);
642     if (!NT_SUCCESS(Status))
643     {
644         TI_DbgPrint(MIN_TRACE, ("Failed to set DACL to security descriptor (0x%X)\n", Status));
645         goto Quit;
646     }
647 
648     Status = RtlSetGroupSecurityDescriptor(&AbsSD,
649                                            SeExports->SeLocalSystemSid,
650                                            FALSE);
651     if (!NT_SUCCESS(Status))
652     {
653         TI_DbgPrint(MIN_TRACE, ("Failed to set group to security descriptor (0x%X)\n", Status));
654         goto Quit;
655     }
656 
657     Status = RtlSetOwnerSecurityDescriptor(&AbsSD,
658                                            SeExports->SeAliasAdminsSid,
659                                            FALSE);
660     if (!NT_SUCCESS(Status))
661     {
662         TI_DbgPrint(MIN_TRACE, ("Failed to set owner to security descriptor (0x%X)\n", Status));
663         goto Quit;
664     }
665 
666     /* Get the required buffer size for the self-relative SD */
667     Status = RtlAbsoluteToSelfRelativeSD(&AbsSD,
668                                          NULL,
669                                          &RelSDSize);
670     if (Status != STATUS_BUFFER_TOO_SMALL)
671     {
672         TI_DbgPrint(MIN_TRACE, ("Expected STATUS_BUFFER_TOO_SMALL but got something else (0x%X)\n", Status));
673         goto Quit;
674     }
675 
676     RelSD = ExAllocatePoolWithTag(PagedPool,
677                                   RelSDSize,
678                                   DEVICE_OBJ_SECURITY_TAG);
679     if (RelSD == NULL)
680     {
681         TI_DbgPrint(MIN_TRACE, ("Failed to allocate buffer heap for relative SD\n"));
682         Status = STATUS_INSUFFICIENT_RESOURCES;
683         goto Quit;
684     }
685 
686     /* Convert it now */
687     Status = RtlAbsoluteToSelfRelativeSD(&AbsSD,
688                                          RelSD,
689                                          &RelSDSize);
690     if (!NT_SUCCESS(Status))
691     {
692         TI_DbgPrint(MIN_TRACE, ("Failed to convert absolute SD into a relative SD (0x%X)\n", Status));
693         goto Quit;
694     }
695 
696     /* Give the buffer to caller */
697     *SecurityDescriptor = RelSD;
698 
699 Quit:
700     if (!NT_SUCCESS(Status))
701     {
702         if (RelSD != NULL)
703         {
704             ExFreePoolWithTag(RelSD, DEVICE_OBJ_SECURITY_TAG);
705         }
706     }
707 
708     if (Dacl != NULL)
709     {
710         ExFreePoolWithTag(Dacl, DEVICE_OBJ_SECURITY_TAG);
711     }
712 
713     return Status;
714 }
715 
716 static
717 NTSTATUS TiSetupTcpDeviceSD(
718     _In_ PDEVICE_OBJECT DeviceObject)
719 {
720     NTSTATUS Status;
721     PSECURITY_DESCRIPTOR Sd;
722     SECURITY_INFORMATION Info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
723 
724     /* Obtain a security descriptor */
725     Status = TiCreateSecurityDescriptor(&Sd);
726     if (!NT_SUCCESS(Status))
727     {
728         TI_DbgPrint(MIN_TRACE, ("Failed to create a security descriptor for the device object\n"));
729         return Status;
730     }
731 
732     /* Whack the new descriptor into the TCP device object */
733     Status = ObSetSecurityObjectByPointer(DeviceObject,
734                                           Info,
735                                           Sd);
736     if (!NT_SUCCESS(Status))
737     {
738         TI_DbgPrint(MIN_TRACE, ("Failed to set new security information to the device object\n"));
739     }
740 
741     ExFreePoolWithTag(Sd, DEVICE_OBJ_SECURITY_TAG);
742     return Status;
743 }
744 
745 static
746 NTSTATUS TiSecurityStartup(
747     VOID)
748 {
749     NTSTATUS Status;
750 
751     /* Set security data for the TCP and IP device objects */
752     Status = TiSetupTcpDeviceSD(TCPDeviceObject);
753     if (!NT_SUCCESS(Status))
754     {
755         TI_DbgPrint(MIN_TRACE, ("Failed to set security data for TCP device object\n"));
756         return Status;
757     }
758 
759     Status = TiSetupTcpDeviceSD(IPDeviceObject);
760     if (!NT_SUCCESS(Status))
761     {
762         TI_DbgPrint(MIN_TRACE, ("Failed to set security data for IP device object\n"));
763         return Status;
764     }
765 
766     return STATUS_SUCCESS;
767 }
768 
769 
770 VOID NTAPI TiUnload(
771   PDRIVER_OBJECT DriverObject)
772 /*
773  * FUNCTION: Unloads the driver
774  * ARGUMENTS:
775  *     DriverObject = Pointer to driver object created by the system
776  */
777 {
778 #if DBG
779   KIRQL OldIrql;
780 
781     TcpipAcquireSpinLock(&AddressFileListLock, &OldIrql);
782     if (!IsListEmpty(&AddressFileListHead)) {
783         TI_DbgPrint(MIN_TRACE, ("[TCPIP, TiUnload] Called. Open address file objects exists.\n"));
784     }
785     TcpipReleaseSpinLock(&AddressFileListLock, OldIrql);
786 #endif
787     /* Cancel timer */
788     KeCancelTimer(&IPTimer);
789 
790     /* Unregister loopback adapter */
791     LoopUnregisterAdapter(NULL);
792 
793     /* Unregister protocol with NDIS */
794     LANUnregisterProtocol();
795 
796     /* Shutdown transport level protocol subsystems */
797     TCPShutdown();
798     UDPShutdown();
799     RawIPShutdown();
800     ICMPShutdown();
801 
802     /* Shutdown network level protocol subsystem */
803     IPShutdown();
804 
805     /* Free NDIS buffer descriptors */
806     if (GlobalBufferPool)
807         NdisFreeBufferPool(GlobalBufferPool);
808 
809     /* Free NDIS packet descriptors */
810     if (GlobalPacketPool)
811         NdisFreePacketPool(GlobalPacketPool);
812 
813     /* Release all device objects */
814 
815     if (TCPDeviceObject)
816         IoDeleteDevice(TCPDeviceObject);
817 
818     if (UDPDeviceObject)
819         IoDeleteDevice(UDPDeviceObject);
820 
821     if (RawIPDeviceObject)
822         IoDeleteDevice(RawIPDeviceObject);
823 
824     if (IPDeviceObject) {
825         ChewShutdown();
826         IoDeleteDevice(IPDeviceObject);
827     }
828 
829     if (EntityList)
830         ExFreePoolWithTag(EntityList, TDI_ENTITY_TAG);
831 
832     TI_DbgPrint(MAX_TRACE, ("[TCPIP, TiUnload] Leaving.\n"));
833 }
834 
835 NTSTATUS NTAPI
836 DriverEntry(
837     PDRIVER_OBJECT DriverObject,
838     PUNICODE_STRING RegistryPath)
839 /*
840  * FUNCTION: Main driver entry point
841  * ARGUMENTS:
842  *     DriverObject = Pointer to a driver object for this driver
843  *     RegistryPath = Registry node for configuration parameters
844  * RETURNS:
845  *     Status of driver initialization
846  */
847 {
848     NTSTATUS Status;
849     UNICODE_STRING strIpDeviceName = RTL_CONSTANT_STRING(DD_IP_DEVICE_NAME);
850     UNICODE_STRING strRawDeviceName = RTL_CONSTANT_STRING(DD_RAWIP_DEVICE_NAME);
851     UNICODE_STRING strUdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
852     UNICODE_STRING strTcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
853     UNICODE_STRING strNdisDeviceName = RTL_CONSTANT_STRING(TCPIP_PROTOCOL_NAME);
854     NDIS_STATUS NdisStatus;
855     LARGE_INTEGER DueTime;
856 
857     TI_DbgPrint(MAX_TRACE, ("[TCPIP, DriverEntry] Called\n"));
858 
859     /* TdiInitialize() ? */
860 
861     /* FIXME: Create symbolic links in Win32 namespace */
862 
863     /* Initialize our periodic timer and its associated DPC object. When the
864         timer expires, the IPTimeout deferred procedure call (DPC) is queued */
865     KeInitializeDpc(&IPTimeoutDpc, IPTimeoutDpcFn, NULL);
866     KeInitializeTimer(&IPTimer);
867 
868     /* Create IP device object */
869     Status = IoCreateDevice(DriverObject, 0, &strIpDeviceName,
870         FILE_DEVICE_NETWORK, 0, FALSE, &IPDeviceObject);
871     if (!NT_SUCCESS(Status)) {
872         TI_DbgPrint(MIN_TRACE, ("Failed to create IP device object. Status (0x%X).\n", Status));
873         TiUnload(DriverObject);
874         return Status;
875     }
876 
877     ChewInit( IPDeviceObject );
878 
879     /* Create RawIP device object */
880     Status = IoCreateDevice(DriverObject, 0, &strRawDeviceName,
881         FILE_DEVICE_NETWORK, 0, FALSE, &RawIPDeviceObject);
882     if (!NT_SUCCESS(Status)) {
883         TI_DbgPrint(MIN_TRACE, ("Failed to create RawIP device object. Status (0x%X).\n", Status));
884         TiUnload(DriverObject);
885         return Status;
886     }
887 
888     /* Create UDP device object */
889     Status = IoCreateDevice(DriverObject, 0, &strUdpDeviceName,
890         FILE_DEVICE_NETWORK, 0, FALSE, &UDPDeviceObject);
891     if (!NT_SUCCESS(Status)) {
892         TI_DbgPrint(MIN_TRACE, ("Failed to create UDP device object. Status (0x%X).\n", Status));
893         TiUnload(DriverObject);
894         return Status;
895     }
896 
897     /* Create TCP device object */
898     Status = IoCreateDevice(DriverObject, 0, &strTcpDeviceName,
899         FILE_DEVICE_NETWORK, 0, FALSE, &TCPDeviceObject);
900     if (!NT_SUCCESS(Status)) {
901         TI_DbgPrint(MIN_TRACE, ("Failed to create TCP device object. Status (0x%X).\n", Status));
902         TiUnload(DriverObject);
903         return Status;
904     }
905 
906     /* Setup network layer and transport layer entities */
907     KeInitializeSpinLock(&EntityListLock);
908     EntityList = ExAllocatePoolWithTag(NonPagedPool,
909                                        sizeof(TDIEntityID) * MAX_TDI_ENTITIES,
910                                        TDI_ENTITY_TAG );
911     if (!EntityList) {
912         TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
913         TiUnload(DriverObject);
914         return STATUS_INSUFFICIENT_RESOURCES;
915     }
916 
917     EntityCount = 0;
918     EntityMax   = MAX_TDI_ENTITIES;
919 
920     /* Allocate NDIS packet descriptors */
921     NdisAllocatePacketPoolEx(&NdisStatus, &GlobalPacketPool, 500, 1500, sizeof(PACKET_CONTEXT));
922     if (NdisStatus != NDIS_STATUS_SUCCESS) {
923         TiUnload(DriverObject);
924         return STATUS_INSUFFICIENT_RESOURCES;
925     }
926 
927     /* Allocate NDIS buffer descriptors */
928     NdisAllocateBufferPool(&NdisStatus, &GlobalBufferPool, 2000);
929     if (NdisStatus != NDIS_STATUS_SUCCESS) {
930         TiUnload(DriverObject);
931         return STATUS_INSUFFICIENT_RESOURCES;
932     }
933 
934     /* Initialize address file list and protecting spin lock */
935     InitializeListHead(&AddressFileListHead);
936     KeInitializeSpinLock(&AddressFileListLock);
937 
938     /* Initialize connection endpoint list and protecting spin lock */
939     InitializeListHead(&ConnectionEndpointListHead);
940     KeInitializeSpinLock(&ConnectionEndpointListLock);
941 
942     /* Initialize interface list and protecting spin lock */
943     InitializeListHead(&InterfaceListHead);
944     KeInitializeSpinLock(&InterfaceListLock);
945 
946     /* Initialize network level protocol subsystem */
947     IPStartup(RegistryPath);
948 
949     /* Initialize transport level protocol subsystems */
950     Status = RawIPStartup();
951     if( !NT_SUCCESS(Status) ) {
952         TiUnload(DriverObject);
953         return Status;
954     }
955 
956     Status = UDPStartup();
957     if( !NT_SUCCESS(Status) ) {
958         TiUnload(DriverObject);
959         return Status;
960     }
961 
962     Status = TCPStartup();
963     if( !NT_SUCCESS(Status) ) {
964         TiUnload(DriverObject);
965         return Status;
966     }
967 
968     Status = ICMPStartup();
969     if( !NT_SUCCESS(Status) ) {
970         TiUnload(DriverObject);
971         return Status;
972     }
973 
974     /* Initialize security */
975     Status = TiSecurityStartup();
976     if (!NT_SUCCESS(Status))
977     {
978         TiUnload(DriverObject);
979         return Status;
980     }
981 
982     /* Use direct I/O */
983     IPDeviceObject->Flags    |= DO_DIRECT_IO;
984     RawIPDeviceObject->Flags |= DO_DIRECT_IO;
985     UDPDeviceObject->Flags   |= DO_DIRECT_IO;
986     TCPDeviceObject->Flags   |= DO_DIRECT_IO;
987 
988     /* Initialize the driver object with this driver's entry points */
989     DriverObject->MajorFunction[IRP_MJ_CREATE]  = TiDispatchOpenClose;
990     DriverObject->MajorFunction[IRP_MJ_CLOSE]   = TiDispatchOpenClose;
991     DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TiDispatchInternal;
992     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TiDispatch;
993 
994     DriverObject->DriverUnload = TiUnload;
995 
996     /* Open loopback adapter */
997     Status = LoopRegisterAdapter(NULL, NULL);
998     if (!NT_SUCCESS(Status)) {
999         TI_DbgPrint(MIN_TRACE, ("Failed to create loopback adapter. Status (0x%X).\n", Status));
1000         TiUnload(DriverObject);
1001         return Status;
1002     }
1003 
1004     /* Register protocol with NDIS */
1005     /* This used to be IP_DEVICE_NAME but the DDK says it has to match your entry in the SCM */
1006     Status = LANRegisterProtocol(&strNdisDeviceName);
1007     if (!NT_SUCCESS(Status)) {
1008         TI_DbgPrint(MIN_TRACE,("Failed to register protocol with NDIS; status 0x%x\n", Status));
1009         TiWriteErrorLog(
1010         DriverObject,
1011         EVENT_TRANSPORT_REGISTER_FAILED,
1012         TI_ERROR_DRIVERENTRY,
1013         Status,
1014         NULL,
1015         0,
1016         NULL);
1017         TiUnload(DriverObject);
1018         return Status;
1019     }
1020 
1021     /* Start the periodic timer with an initial and periodic
1022         relative expiration time of IP_TIMEOUT milliseconds */
1023     DueTime.QuadPart = -(LONGLONG)IP_TIMEOUT * 10000;
1024     KeSetTimerEx(&IPTimer, DueTime, IP_TIMEOUT, &IPTimeoutDpc);
1025 
1026     TI_DbgPrint(MAX_TRACE, ("[TCPIP, DriverEntry] Finished\n"));
1027 
1028 
1029     return STATUS_SUCCESS;
1030 }
1031 
1032 VOID NTAPI
1033 IPAddInterface(
1034     ULONG   Unknown0,
1035     ULONG   Unknown1,
1036     ULONG   Unknown2,
1037     ULONG   Unknown3,
1038     ULONG   Unknown4)
1039 {
1040     UNIMPLEMENTED;
1041 }
1042 
1043 
1044 VOID NTAPI
1045 IPDelInterface(
1046     ULONG   Unknown0)
1047 {
1048     UNIMPLEMENTED;
1049 }
1050 
1051 
1052 VOID NTAPI
1053 LookupRoute(
1054     ULONG   Unknown0,
1055     ULONG   Unknown1)
1056 {
1057     UNIMPLEMENTED;
1058 }
1059 
1060 /* EOF */
1061