2 * Copyright (c) 1999, 2000
3 * Politecnico di Torino. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
28 #include <ddk/ntddk.h>
37 #include "win_bpf_filter_init.h"
42 // Declare the global debug flag for this driver.
43 //ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
44 ULONG PacketDebugFlag
= PACKET_DEBUG_LOUD
+ PACKET_DEBUG_VERY_LOUD
+ PACKET_DEBUG_INIT
;
48 PDEVICE_EXTENSION GlobalDeviceExtension
;
50 ////////////////////////////////////////////////////////////////////////////////
54 #define NDIS_STRING_CONST(x) {sizeof(L##x)-2, sizeof(L##x), L##x}
56 //void __moddi3(void) {}
57 //void __divdi3(void) {}
59 #endif // ROBERTS_PATCH
60 ////////////////////////////////////////////////////////////////////////////////
64 NDIS_STRING NPF_Prefix
= NDIS_STRING_CONST("NPF_");
65 NDIS_STRING devicePrefix
= NDIS_STRING_CONST("\\Device\\");
66 NDIS_STRING symbolicLinkPrefix
= NDIS_STRING_CONST("\\DosDevices\\");
67 NDIS_STRING tcpLinkageKeyName
= NDIS_STRING_CONST("\\Registry\\Machine\\System"
68 L
"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
69 NDIS_STRING AdapterListKey
= NDIS_STRING_CONST("\\Registry\\Machine\\System"
70 L
"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
71 NDIS_STRING bindValueName
= NDIS_STRING_CONST("Bind");
74 /// Global variable that points to the names of the bound adapters
77 extern struct time_conv G_Start_Time
; // from openclos.c
79 extern NDIS_SPIN_LOCK Opened_Instances_Lock
;
82 // Packet Driver's entry routine.
89 IN PDRIVER_OBJECT DriverObject
,
90 IN PUNICODE_STRING RegistryPath
94 NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar
;
95 UNICODE_STRING MacDriverName
;
96 UNICODE_STRING UnicodeDeviceName
;
97 PDEVICE_OBJECT DeviceObject
= NULL
;
98 PDEVICE_EXTENSION DeviceExtension
= NULL
;
99 NTSTATUS Status
= STATUS_SUCCESS
;
100 NTSTATUS ErrorCode
= STATUS_SUCCESS
;
101 NDIS_STRING ProtoName
= NDIS_STRING_CONST("PacketDriver");
102 ULONG DevicesCreated
=0;
105 PWSTR BindStringSave
;
106 PWSTR ExportStringSave
;
107 NDIS_HANDLE NdisProtocolHandle
;
109 PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP
;
110 UNICODE_STRING macName
;
112 // This driver at the moment works only on single processor machines
113 if(NdisSystemProcessorCount() != 1){
114 return STATUS_IMAGE_MP_UP_MISMATCH
;
117 IF_LOUD(DbgPrint("Packet: DriverEntry\n");)
119 RtlZeroMemory(&ProtocolChar
,sizeof(NDIS_PROTOCOL_CHARACTERISTICS
));
122 ProtocolChar
.MajorNdisVersion
= 5;
124 ProtocolChar
.MajorNdisVersion
= 3;
126 ProtocolChar
.MinorNdisVersion
= 0;
128 ProtocolChar
.Reserved
= 0;
130 ProtocolChar
.u1
.Reserved
= 0;
132 ProtocolChar
.OpenAdapterCompleteHandler
= NPF_OpenAdapterComplete
;
133 ProtocolChar
.CloseAdapterCompleteHandler
= NPF_CloseAdapterComplete
;
135 ProtocolChar
.SendCompleteHandler
= NPF_SendComplete
;
136 ProtocolChar
.TransferDataCompleteHandler
= NPF_TransferDataComplete
;
138 ProtocolChar
.u2
.SendCompleteHandler
= NPF_SendComplete
;
139 ProtocolChar
.u3
.TransferDataCompleteHandler
= NPF_TransferDataComplete
;
141 ProtocolChar
.ResetCompleteHandler
= NPF_ResetComplete
;
142 ProtocolChar
.RequestCompleteHandler
= NPF_RequestComplete
;
144 ProtocolChar
.ReceiveHandler
= NPF_tap
;
146 ProtocolChar
.u4
.ReceiveHandler
= NPF_tap
;
148 ProtocolChar
.ReceiveCompleteHandler
= NPF_ReceiveComplete
;
149 ProtocolChar
.StatusHandler
= NPF_Status
;
150 ProtocolChar
.StatusCompleteHandler
= NPF_StatusComplete
;
152 ProtocolChar
.BindAdapterHandler
= NPF_BindAdapter
;
153 ProtocolChar
.UnbindAdapterHandler
= NPF_UnbindAdapter
;
154 ProtocolChar
.PnPEventHandler
= NPF_PowerChange
;
155 ProtocolChar
.ReceivePacketHandler
= NULL
;
157 ProtocolChar
.Name
= ProtoName
;
159 NdisRegisterProtocol(
163 sizeof(NDIS_PROTOCOL_CHARACTERISTICS
));
165 if (Status
!= NDIS_STATUS_SUCCESS
) {
167 IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
173 NdisAllocateSpinLock(&Opened_Instances_Lock
);
175 // Set up the device driver entry points.
176 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = NPF_Open
;
177 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = NPF_Close
;
178 DriverObject
->MajorFunction
[IRP_MJ_READ
] = NPF_Read
;
179 DriverObject
->MajorFunction
[IRP_MJ_WRITE
] = NPF_Write
;
180 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = NPF_IoControl
;
181 DriverObject
->DriverUnload
= NPF_Unload
;
184 // Get the name of the Packet driver and the name of the NIC driver
185 // to bind to from the registry
186 Status=NPF_ReadRegistry(
192 if (Status != STATUS_SUCCESS) {
194 IF_LOUD(DbgPrint("Trying dynamic binding\n");)
196 bindP
= getAdaptersList();
199 IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
201 tcpBindingsP
= getTcpBindings();
203 if (tcpBindingsP
== NULL
){
204 IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
208 bindP
= (WCHAR
*)tcpBindingsP
;
209 bindT
= (WCHAR
*)(tcpBindingsP
->Data
);
214 for (; *bindT
!= UNICODE_NULL
; bindT
+= (macName
.Length
+ sizeof(UNICODE_NULL
)) / sizeof(WCHAR
)) {
215 RtlInitUnicodeString(&macName
, bindT
);
216 createDevice(DriverObject
, &macName
, NdisProtocolHandle
);
219 return STATUS_SUCCESS
;
222 BindStringSave = BindString;
223 ExportStringSave = ExportString;
225 // create a device object for each entry
227 while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) {
229 // Create a counted unicode string for both null terminated strings
231 RtlInitUnicodeString(
234 RtlInitUnicodeString(
238 // Advance to the next string of the MULTI_SZ string
240 BindString += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
241 ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
242 IF_LOUD(DbgPrint("NPF: DeviceName=%ws MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);)
244 // Create the device object
246 Status = IoCreateDevice(
248 sizeof(DEVICE_EXTENSION),
250 FILE_DEVICE_PROTOCOL,
254 if (Status != STATUS_SUCCESS) {
255 IF_LOUD(DbgPrint("NPF: IoCreateDevice() failed:\n");)
259 DeviceObject->Flags |= DO_DIRECT_IO;
260 DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
261 DeviceExtension->DeviceObject = DeviceObject;
263 // Save the the name of the MAC driver to open in the Device Extension
265 DeviceExtension->AdapterName=MacDriverName;
266 if (DevicesCreated == 1) {
267 DeviceExtension->BindString = NULL;
268 DeviceExtension->ExportString = NULL;
270 DeviceExtension->NdisProtocolHandle=NdisProtocolHandle;
272 if (DevicesCreated > 0) {
274 // Managed to create at least one device.
276 IF_LOUD(DbgPrint("NPF: Managed to create at least one device.\n");)
277 return STATUS_SUCCESS;
279 ExFreePool(BindStringSave);
280 ExFreePool(ExportStringSave);
284 IF_LOUD(DbgPrint("NPF: RegistryError: calling NdisDeregisterProtocol()\n");)
285 NdisDeregisterProtocol(
290 Status
=STATUS_UNSUCCESSFUL
;
296 //-------------------------------------------------------------------
298 PWCHAR
getAdaptersList(void)
300 PKEY_VALUE_PARTIAL_INFORMATION result
= NULL
;
301 OBJECT_ATTRIBUTES objAttrs
;
306 #define NPF_TAG_DEVICENAME TAG('0', 'P', 'W', 'A')
307 PWCHAR DeviceNames
= (PWCHAR
) ExAllocatePoolWithTag(PagedPool
, 4096, NPF_TAG_DEVICENAME
);
309 if (DeviceNames
== NULL
) {
310 IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
314 InitializeObjectAttributes(&objAttrs
, &AdapterListKey
,
315 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
316 status
= ZwOpenKey(&keyHandle
, KEY_READ
, &objAttrs
);
317 if (!NT_SUCCESS(status
)) {
319 //IF_LOUD(DbgPrint("Status of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
320 IF_LOUD(DbgPrint("Status of %x opening %ws\n", status
, AdapterListKey
.Buffer
);)
324 KEY_VALUE_PARTIAL_INFORMATION valueInfo
;
328 IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames
);)
330 // Scan the list of the devices
331 while((status
=ZwEnumerateKey(keyHandle
,i
,KeyBasicInformation
,AdapInfo
,sizeof(AdapInfo
),&resultLength
))==STATUS_SUCCESS
) {
332 WCHAR ExportKeyName
[512];
333 PWCHAR ExportKeyPrefix
= L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
334 UINT ExportKeyPrefixSize
= sizeof(L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
335 PWCHAR LinkageKeyPrefix
= L
"\\Linkage";
336 UINT LinkageKeyPrefixSize
= sizeof(L
"\\Linkage");
337 NDIS_STRING FinalExportKey
= NDIS_STRING_CONST("Export");
338 PKEY_BASIC_INFORMATION tInfo
= (PKEY_BASIC_INFORMATION
)AdapInfo
;
339 UNICODE_STRING AdapterKeyName
;
340 HANDLE ExportKeyHandle
;
341 KEY_VALUE_PARTIAL_INFORMATION valueInfo
;
344 RtlCopyMemory(ExportKeyName
,
346 ExportKeyPrefixSize
);
348 RtlCopyMemory((PCHAR
)ExportKeyName
+ExportKeyPrefixSize
,
350 tInfo
->NameLength
+2);
352 RtlCopyMemory((PCHAR
)ExportKeyName
+ExportKeyPrefixSize
+tInfo
->NameLength
,
354 LinkageKeyPrefixSize
);
356 IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName
);)
358 RtlInitUnicodeString(&AdapterKeyName
, ExportKeyName
);
360 InitializeObjectAttributes(&objAttrs
, &AdapterKeyName
,
361 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
363 status
=ZwOpenKey(&ExportKeyHandle
,KEY_READ
,&objAttrs
);
365 if (!NT_SUCCESS(status
)) {
366 DbgPrint("OpenKey Failed, %d!\n",status
);
371 status
= ZwQueryValueKey(ExportKeyHandle
, &FinalExportKey
,
372 KeyValuePartialInformation
, &valueInfo
,
373 sizeof(valueInfo
), &resultLength
);
375 if (!NT_SUCCESS(status
) && (status
!= STATUS_BUFFER_OVERFLOW
)) {
376 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status
);)
377 } else { // We know how big it needs to be.
378 ULONG valueInfoLength
= valueInfo
.DataLength
+ FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
379 #define NPF_TAG_KEYVALUE TAG('1', 'P', 'W', 'A')
380 PKEY_VALUE_PARTIAL_INFORMATION valueInfoP
= (PKEY_VALUE_PARTIAL_INFORMATION
) ExAllocatePoolWithTag(PagedPool
, valueInfoLength
, NPF_TAG_KEYVALUE
);
381 if (valueInfoP
!= NULL
) {
382 status
= ZwQueryValueKey(ExportKeyHandle
, &FinalExportKey
,
383 KeyValuePartialInformation
,
385 valueInfoLength
, &resultLength
);
386 if (!NT_SUCCESS(status
)) {
387 IF_LOUD(DbgPrint("Status of %x querying key value\n", status
);)
389 IF_LOUD(DbgPrint("Device %d = %ws\n", i
, valueInfoP
->Data
);)
390 RtlCopyMemory((PCHAR
)DeviceNames
+BufPos
,
392 valueInfoP
->DataLength
);
393 BufPos
+=valueInfoP
->DataLength
-2;
396 ExFreePool(valueInfoP
);
398 IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
403 // terminate the buffer
404 DeviceNames
[BufPos
/2]=0;
405 DeviceNames
[BufPos
/2+1]=0;
407 ZwClose (ExportKeyHandle
);
416 ExFreePool(DeviceNames
);
422 //-------------------------------------------------------------------
424 PKEY_VALUE_PARTIAL_INFORMATION
getTcpBindings(void)
426 PKEY_VALUE_PARTIAL_INFORMATION result
= NULL
;
427 OBJECT_ATTRIBUTES objAttrs
;
431 InitializeObjectAttributes(&objAttrs
, &tcpLinkageKeyName
,
432 OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
433 status
= ZwOpenKey(&keyHandle
, KEY_READ
, &objAttrs
);
434 if (!NT_SUCCESS(status
)) {
435 IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status
, tcpLinkageKeyName
.Buffer
);)
438 KEY_VALUE_PARTIAL_INFORMATION valueInfo
;
440 IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName
.Buffer
);)
442 status
= ZwQueryValueKey(keyHandle
, &bindValueName
,
443 KeyValuePartialInformation
, &valueInfo
,
444 sizeof(valueInfo
), &resultLength
);
445 if (!NT_SUCCESS(status
) && (status
!= STATUS_BUFFER_OVERFLOW
)) {
446 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status
);)
447 } else { // We know how big it needs to be.
448 ULONG valueInfoLength
= valueInfo
.DataLength
+ FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
[0]);
449 #define NPF_TAG_KEYVALUE2 TAG('2', 'P', 'W', 'A')
450 PKEY_VALUE_PARTIAL_INFORMATION valueInfoP
=
451 (PKEY_VALUE_PARTIAL_INFORMATION
)ExAllocatePoolWithTag(PagedPool
, valueInfoLength
, NPF_TAG_KEYVALUE2
);
453 if (valueInfoP
!= NULL
) {
454 status
= ZwQueryValueKey(keyHandle
, &bindValueName
,
455 KeyValuePartialInformation
,
457 valueInfoLength
, &resultLength
);
459 if (!NT_SUCCESS(status
)) {
460 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status
);)
462 else if (valueInfoLength
!= resultLength
) {
463 IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
464 "but previous len = %u\n",
465 resultLength
, valueInfoLength
);)
467 else if (valueInfoP
->Type
!= REG_MULTI_SZ
) {
468 IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
474 WCHAR
* dataP
= (WCHAR
*)(&valueInfoP
->Data
[0]);
475 IF_LOUD(DbgPrint("\n\nBind value:\n");)
476 for (i
= 0; *dataP
!= UNICODE_NULL
; i
++) {
477 UNICODE_STRING macName
;
478 RtlInitUnicodeString(&macName
, dataP
);
479 IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i
, macName
.Buffer
);)
481 (macName
.Length
+ sizeof(UNICODE_NULL
)) / sizeof(WCHAR
);
493 //-------------------------------------------------------------------
495 BOOLEAN
createDevice(IN OUT PDRIVER_OBJECT adriverObjectP
,
496 IN PUNICODE_STRING amacNameP
, NDIS_HANDLE aProtoHandle
)
499 PDEVICE_OBJECT devObjP
;
500 UNICODE_STRING deviceName
;
501 UNICODE_STRING deviceSymLink
;
503 IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP
->Buffer
););
504 if (RtlCompareMemory(amacNameP
->Buffer
, devicePrefix
.Buffer
,
505 devicePrefix
.Length
) < devicePrefix
.Length
) {
509 deviceName
.Length
= 0;
510 deviceName
.MaximumLength
= (USHORT
)(amacNameP
->Length
+ NPF_Prefix
.Length
+ sizeof(UNICODE_NULL
));
511 #define NPF_TAG_DEVICENAMEBUF TAG('3', 'P', 'W', 'A')
512 deviceName
.Buffer
= ExAllocatePoolWithTag(PagedPool
, deviceName
.MaximumLength
, NPF_TAG_DEVICENAMEBUF
);
514 if (deviceName
.Buffer
== NULL
)
517 deviceSymLink
.Length
= 0;
518 deviceSymLink
.MaximumLength
=(USHORT
)(amacNameP
->Length
-devicePrefix
.Length
519 + symbolicLinkPrefix
.Length
521 + sizeof(UNICODE_NULL
));
523 #define NPF_TAG_SYMLINKBUF TAG('3', 'P', 'W', 'A')
524 deviceSymLink
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
, deviceSymLink
.MaximumLength
, NPF_TAG_SYMLINKBUF
);
526 if (deviceSymLink
.Buffer
== NULL
)
528 ExFreePool(deviceName
.Buffer
);
532 RtlAppendUnicodeStringToString(&deviceName
, &devicePrefix
);
533 RtlAppendUnicodeStringToString(&deviceName
, &NPF_Prefix
);
534 RtlAppendUnicodeToString(&deviceName
, amacNameP
->Buffer
+
535 devicePrefix
.Length
/ sizeof(WCHAR
));
537 RtlAppendUnicodeStringToString(&deviceSymLink
, &symbolicLinkPrefix
);
538 RtlAppendUnicodeStringToString(&deviceSymLink
, &NPF_Prefix
);
539 RtlAppendUnicodeToString(&deviceSymLink
, amacNameP
->Buffer
+
540 devicePrefix
.Length
/ sizeof(WCHAR
));
542 IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName
.Buffer
);)
544 status
= IoCreateDevice(adriverObjectP
,
545 sizeof(PDEVICE_EXTENSION
),
547 FILE_DEVICE_TRANSPORT
,
552 if (NT_SUCCESS(status
)) {
553 PDEVICE_EXTENSION devExtP
= (PDEVICE_EXTENSION
)devObjP
->DeviceExtension
;
555 IF_LOUD(DbgPrint("Device created successfully\n"););
557 devObjP
->Flags
|= DO_DIRECT_IO
;
558 RtlInitUnicodeString(&devExtP
->AdapterName
,amacNameP
->Buffer
);
559 devExtP
->NdisProtocolHandle
=aProtoHandle
;
561 IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink
.Buffer
););
563 if (IoCreateSymbolicLink(&deviceSymLink
,&deviceName
) != STATUS_SUCCESS
) {
564 IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink
.Buffer
););
566 ExFreePool(deviceName
.Buffer
);
567 ExFreePool(deviceSymLink
.Buffer
);
569 devExtP
->ExportString
= NULL
;
574 IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink
.Buffer
););
576 devExtP
->ExportString
= deviceSymLink
.Buffer
;
578 ExFreePool(deviceName
.Buffer
);
585 IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status
););
587 ExFreePool(deviceName
.Buffer
);
588 ExFreePool(deviceSymLink
.Buffer
);
594 //-------------------------------------------------------------------
597 NPF_Unload(IN PDRIVER_OBJECT DriverObject
)
599 PDEVICE_OBJECT DeviceObject
;
600 PDEVICE_OBJECT OldDeviceObject
;
601 PDEVICE_EXTENSION DeviceExtension
;
603 NDIS_HANDLE NdisProtocolHandle
;
608 IF_LOUD(DbgPrint("NPF: Unload\n"););
610 DeviceObject
= DriverObject
->DeviceObject
;
612 while (DeviceObject
!= NULL
) {
613 OldDeviceObject
=DeviceObject
;
615 DeviceObject
=DeviceObject
->NextDevice
;
617 DeviceExtension
= OldDeviceObject
->DeviceExtension
;
619 NdisProtocolHandle
=DeviceExtension
->NdisProtocolHandle
;
621 IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
622 DeviceExtension
->AdapterName
.Buffer
,
627 if (DeviceExtension
->ExportString
)
629 RtlInitUnicodeString(&SymLink
, DeviceExtension
->ExportString
);
631 IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink
.Buffer
););
633 IoDeleteSymbolicLink(&SymLink
);
634 ExFreePool(DeviceExtension
->ExportString
);
637 IoDeleteDevice(OldDeviceObject
);
640 NdisDeregisterProtocol(
645 // Free the adapters names
649 //-------------------------------------------------------------------
652 NPF_IoControl(IN PDEVICE_OBJECT DeviceObject
,IN PIRP Irp
)
655 PIO_STACK_LOCATION IrpSp
;
656 PLIST_ENTRY RequestListEntry
;
657 PINTERNAL_REQUEST pRequest
;
660 PLIST_ENTRY PacketListEntry
;
665 PPACKET_OID_DATA OidData
;
667 PNDIS_PACKET pPacket
;
670 PUCHAR TmpBPFProgram
;
672 BOOLEAN SyncWrite
= FALSE
;
673 struct bpf_insn
*initprogram
;
676 BOOLEAN IsExtendedFilter
=FALSE
;
678 IF_LOUD(DbgPrint("NPF: IoControl\n");)
680 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
681 FunctionCode
=IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
;
682 Open
=IrpSp
->FileObject
->FsContext
;
684 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
686 IF_LOUD(DbgPrint("NPF: Function code is %08lx buff size=%08lx %08lx\n",FunctionCode
,IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
,IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
);)
689 switch (FunctionCode
){
691 case BIOCGSTATS
: //function to get the capture stats
693 if(IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< 4*sizeof(INT
)){
697 *(((PUINT
)Irp
->UserBuffer
)+3) = Open
->Accepted
;
698 *(((PUINT
)Irp
->UserBuffer
)) = Open
->Received
;
699 *(((PUINT
)Irp
->UserBuffer
)+1) = Open
->Dropped
;
700 *(((PUINT
)Irp
->UserBuffer
)+2) = 0; // Not yet supported
702 EXIT_SUCCESS(4*sizeof(INT
));
706 case BIOCGEVNAME
: //function to get the name of the event associated with the current instance
708 if(IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
<26){
712 RtlCopyMemory(Irp
->UserBuffer
,(Open
->ReadEventName
.Buffer
)+18,26);
718 case BIOCSENDPACKETSSYNC
:
722 case BIOCSENDPACKETSNOSYNC
:
724 WriteRes
= NPF_BufferedWrite(Irp
,
725 (PUCHAR
)Irp
->AssociatedIrp
.SystemBuffer
,
726 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
,
731 EXIT_SUCCESS(WriteRes
);
734 EXIT_FAILURE(WriteRes
);
740 // Free the previous buffer if it was present
741 if(Open
->bpfprogram
!=NULL
){
742 TmpBPFProgram
=Open
->bpfprogram
;
743 Open
->bpfprogram
= NULL
;
744 ExFreePool(TmpBPFProgram
);
747 if (Open
->Filter
!=NULL
)
749 JIT_BPF_Filter
*OldFilter
=Open
->Filter
;
751 BPF_Destroy_JIT_Filter(OldFilter
);
754 // Get the pointer to the new program
755 prog
=(PUCHAR
)Irp
->AssociatedIrp
.SystemBuffer
;
758 IF_LOUD(DbgPrint("0001");)
763 insns
=(IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
)/sizeof(struct bpf_insn
);
765 //count the number of operative instructions
766 for (cnt
=0;(cnt
<insns
) &&(((struct bpf_insn
*)prog
)[cnt
].code
!=BPF_SEPARATION
); cnt
++);
768 IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt
);)
770 if (((struct bpf_insn
*)prog
)[cnt
].code
==BPF_SEPARATION
&& (insns
-cnt
-1)!=0)
772 IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns
-cnt
-1);)
774 IsExtendedFilter
=TRUE
;
776 initprogram
=&((struct bpf_insn
*)prog
)[cnt
+1];
778 if(bpf_filter_init(initprogram
,&(Open
->mem_ex
),&(Open
->tme
), &G_Start_Time
)!=INIT_OK
)
781 IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
787 //the NPF processor has been initialized, we have to validate the operative instructions
790 if(bpf_validate((struct bpf_insn
*)prog
,cnt
,Open
->mem_ex
.size
)==0)
792 IF_LOUD(DbgPrint("Error validating program");)
793 //FIXME: the machine has been initialized(?), but the operative code is wrong.
794 //we have to reset the machine!
795 //something like: reallocate the mem_ex, and reset the tme_core
799 // Allocate the memory to contain the new filter program
800 // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
801 #define NPF_TAG_BPFPROG TAG('4', 'P', 'W', 'A')
802 TmpBPFProgram
=(PUCHAR
)ExAllocatePoolWithTag(NonPagedPool
, cnt
*sizeof(struct bpf_insn
), NPF_TAG_BPFPROG
);
803 if (TmpBPFProgram
==NULL
){
804 IF_LOUD(DbgPrint("Error - No memory for filter");)
809 //copy the program in the new buffer
810 RtlCopyMemory(TmpBPFProgram
,prog
,cnt
*sizeof(struct bpf_insn
));
811 Open
->bpfprogram
=TmpBPFProgram
;
813 // Create the new JIT filter function
814 if(!IsExtendedFilter
)
815 if((Open
->Filter
=BPF_jitter((struct bpf_insn
*)Open
->bpfprogram
,cnt
)) == NULL
) {
816 IF_LOUD(DbgPrint("Error jittering filter");)
823 (INT
)Open
->BLastByte
= -1;
828 EXIT_SUCCESS(IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
832 case BIOCSMODE
: //set the capture mode
834 mode
=*((PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
836 if(mode
== MODE_CAPT
){
837 Open
->mode
=MODE_CAPT
;
841 else if (mode
==MODE_MON
){
847 if(mode
& MODE_STAT
){
848 Open
->mode
= MODE_STAT
;
849 Open
->Nbytes
.QuadPart
=0;
850 Open
->Npackets
.QuadPart
=0;
852 if(Open
->TimeOut
.QuadPart
==0)Open
->TimeOut
.QuadPart
=-10000000;
856 if(mode
& MODE_DUMP
){
858 Open
->mode
|= MODE_DUMP
;
859 Open
->MinToCopy
=(Open
->BufSize
<2000000)?Open
->BufSize
/2:1000000;
869 case BIOCSETDUMPFILENAME
:
871 if(Open
->mode
& MODE_DUMP
)
874 // Close current dump file
875 if(Open
->DumpFileHandle
!= NULL
){
876 NPF_CloseDumpFile(Open
);
877 Open
->DumpFileHandle
= NULL
;
880 if(IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
== 0){
884 // Allocate the buffer that will contain the string
885 #define NPF_TAG_DUMPNAMEBUF TAG('5', 'P', 'W', 'A')
886 DumpNameBuff
=ExAllocatePoolWithTag(NonPagedPool
, IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
, NPF_TAG_DUMPNAMEBUF
);
887 if(DumpNameBuff
==NULL
|| Open
->DumpFileName
.Buffer
!=NULL
){
888 IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
893 RtlCopyBytes((PVOID
)DumpNameBuff
,
894 Irp
->AssociatedIrp
.SystemBuffer
,
895 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);
897 // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
898 ((SHORT
*)DumpNameBuff
)[IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
/2-1]=0;
900 // Create the unicode string
901 RtlInitUnicodeString(&Open
->DumpFileName
, DumpNameBuff
);
903 IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
904 Open
->DumpFileName
.Buffer
,
905 IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);)
907 // Try to create the file
908 if ( NT_SUCCESS( NPF_OpenDumpFile(Open
,&Open
->DumpFileName
,FALSE
)) &&
909 NT_SUCCESS( NPF_StartDump(Open
))){
919 case BIOCSETDUMPLIMITS
:
921 Open
->MaxDumpBytes
= *(PULONG
)Irp
->AssociatedIrp
.SystemBuffer
;
922 Open
->MaxDumpPacks
= *((PULONG
)Irp
->AssociatedIrp
.SystemBuffer
+ 1);
924 IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open
->MaxDumpBytes
, Open
->MaxDumpPacks
);)
930 case BIOCISDUMPENDED
:
931 if(IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
< 4){
935 *((UINT
*)Irp
->UserBuffer
) = (Open
->DumpLimitReached
)?1:0;
941 case BIOCSETBUFFERSIZE
:
943 // Get the number of bytes to allocate
944 dim
= *((PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
946 // Free the old buffer
947 tpointer
= Open
->Buffer
;
948 if(tpointer
!= NULL
){
951 ExFreePool(tpointer
);
953 // Allocate the new buffer
955 #define NPF_TAG_TPOINTER TAG('6', 'P', 'W', 'A')
956 tpointer
= ExAllocatePoolWithTag(NonPagedPool
, dim
, NPF_TAG_TPOINTER
);
957 if (tpointer
==NULL
) {
967 Open
->Buffer
= tpointer
;
970 (INT
)Open
->BLastByte
= -1;
972 Open
->BufSize
= (UINT
)dim
;
977 case BIOCSRTIMEOUT
: //set the timeout on the read calls
979 timeout
= *((PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
981 Open
->TimeOut
.QuadPart
=(LONGLONG
)IMMEDIATE
;
983 Open
->TimeOut
.QuadPart
=(LONGLONG
)timeout
;
984 Open
->TimeOut
.QuadPart
*=10000;
985 Open
->TimeOut
.QuadPart
=-Open
->TimeOut
.QuadPart
;
988 //IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
989 EXIT_SUCCESS(timeout
);
993 case BIOCSWRITEREP
: //set the writes repetition number
995 Open
->Nwrites
= *((PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
997 EXIT_SUCCESS(Open
->Nwrites
);
1001 case BIOCSMINTOCOPY
: //set the minimum buffer's size to copy to the application
1003 Open
->MinToCopy
= *((PULONG
)Irp
->AssociatedIrp
.SystemBuffer
);
1005 EXIT_SUCCESS(Open
->MinToCopy
);
1009 case IOCTL_PROTOCOL_RESET
:
1011 IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
1013 IoMarkIrpPending(Irp
);
1014 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1016 ExInterlockedInsertTailList(&Open
->ResetIrpList
,&Irp
->Tail
.Overlay
.ListEntry
,&Open
->RequestSpinLock
);
1017 NdisReset(&Status
,Open
->AdapterHandle
);
1018 if (Status
!= NDIS_STATUS_PENDING
) {
1019 IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
1020 NPF_ResetComplete(Open
,Status
);
1029 // Extract a request from the list of free ones
1030 RequestListEntry
=ExInterlockedRemoveHeadList(&Open
->RequestList
,&Open
->RequestSpinLock
);
1031 if (RequestListEntry
== NULL
)
1036 pRequest
=CONTAINING_RECORD(RequestListEntry
,INTERNAL_REQUEST
,ListElement
);
1038 pRequest
->Internal
= FALSE
;
1042 // See if it is an Ndis request
1044 OidData
=Irp
->AssociatedIrp
.SystemBuffer
;
1046 if (((FunctionCode
== BIOCSETOID
) || (FunctionCode
== BIOCQUERYOID
))
1048 (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
== IrpSp
->Parameters
.DeviceIoControl
.OutputBufferLength
)
1050 (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(PACKET_OID_DATA
))
1052 (IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
>= sizeof(PACKET_OID_DATA
)-1+OidData
->Length
)) {
1054 IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData
->Oid
,OidData
->Length
);)
1057 // The buffer is valid
1059 if (FunctionCode
== BIOCSETOID
){
1061 pRequest
->Request
.RequestType
=NdisRequestSetInformation
;
1062 pRequest
->Request
.DATA
.SET_INFORMATION
.Oid
=OidData
->Oid
;
1064 pRequest
->Request
.DATA
.SET_INFORMATION
.InformationBuffer
=OidData
->Data
;
1065 pRequest
->Request
.DATA
.SET_INFORMATION
.InformationBufferLength
=OidData
->Length
;
1067 pRequest
->Request
.RequestType
=NdisRequestQueryInformation
;
1068 pRequest
->Request
.DATA
.QUERY_INFORMATION
.Oid
=OidData
->Oid
;
1070 pRequest
->Request
.DATA
.QUERY_INFORMATION
.InformationBuffer
=OidData
->Data
;
1071 pRequest
->Request
.DATA
.QUERY_INFORMATION
.InformationBufferLength
=OidData
->Length
;
1075 NdisResetEvent(&Open
->IOEvent
);
1077 // submit the request
1081 Open
->AdapterHandle
,
1089 Status
=NDIS_STATUS_FAILURE
;
1090 pRequest
->Request
.DATA
.SET_INFORMATION
.BytesRead
=0;
1091 pRequest
->Request
.DATA
.QUERY_INFORMATION
.BytesWritten
=0;
1095 if (Status
!= NDIS_STATUS_PENDING
) {
1096 IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
1098 NPF_RequestComplete(Open
, &pRequest
->Request
, Status
);
1103 NdisWaitEvent(&Open
->IOEvent
, 5000);
1105 return(Open
->IOStatus
);
1118 //-------------------------------------------------------------------
1121 NPF_RequestComplete(
1122 IN NDIS_HANDLE ProtocolBindingContext
,
1123 IN PNDIS_REQUEST NdisRequest
,
1124 IN NDIS_STATUS Status
1128 POPEN_INSTANCE Open
;
1129 PIO_STACK_LOCATION IrpSp
;
1131 PINTERNAL_REQUEST pRequest
;
1135 PPACKET_OID_DATA OidData
;
1137 IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
1139 Open
= (POPEN_INSTANCE
)ProtocolBindingContext
;
1141 pRequest
=CONTAINING_RECORD(NdisRequest
,INTERNAL_REQUEST
,Request
);
1144 if(pRequest
->Internal
== TRUE
){
1146 // Put the request in the list of the free ones
1147 ExInterlockedInsertTailList(&Open
->RequestList
, &pRequest
->ListElement
, &Open
->RequestSpinLock
);
1149 if(Status
!= NDIS_STATUS_SUCCESS
)
1150 Open
->MaxFrameSize
= 1514; // Assume Ethernet
1152 // We always return success, because the adapter has been already opened
1153 Irp
->IoStatus
.Status
= NDIS_STATUS_SUCCESS
;
1154 Irp
->IoStatus
.Information
= 0;
1155 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1159 IrpSp
= IoGetCurrentIrpStackLocation(Irp
);
1161 FunctionCode
=IrpSp
->Parameters
.DeviceIoControl
.IoControlCode
;
1163 OidData
=Irp
->AssociatedIrp
.SystemBuffer
;
1165 if (FunctionCode
== BIOCSETOID
) {
1167 OidData
->Length
=pRequest
->Request
.DATA
.SET_INFORMATION
.BytesRead
;
1171 if (FunctionCode
== BIOCQUERYOID
) {
1173 OidData
->Length
=pRequest
->Request
.DATA
.QUERY_INFORMATION
.BytesWritten
;
1175 IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest
->Request
.DATA
.QUERY_INFORMATION
.BytesWritten
);)
1180 Irp
->IoStatus
.Information
=IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
;
1182 IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp
->Parameters
.DeviceIoControl
.InputBufferLength
);)
1184 ExInterlockedInsertTailList(
1186 &pRequest
->ListElement
,
1187 &Open
->RequestSpinLock
);
1189 Irp
->IoStatus
.Status
= Status
;
1191 Open
->IOStatus
= Status
;
1193 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
1195 // Unlock the caller
1196 NdisSetEvent(&Open
->IOEvent
);
1203 //-------------------------------------------------------------------
1207 IN NDIS_HANDLE ProtocolBindingContext
,
1208 IN NDIS_STATUS Status
,
1209 IN PVOID StatusBuffer
,
1210 IN UINT StatusBufferSize
1215 IF_LOUD(DbgPrint("NPF: Status Indication\n");)
1221 //-------------------------------------------------------------------
1225 IN NDIS_HANDLE ProtocolBindingContext
1230 IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
1236 //-------------------------------------------------------------------
1240 IN PWSTR
*MacDriverName
,
1241 IN PWSTR
*PacketDriverName
,
1242 IN PUNICODE_STRING RegistryPath
1248 RTL_QUERY_REGISTRY_TABLE ParamTable
[4];
1250 PWSTR Bind
= L
"Bind";
1251 PWSTR Export
= L
"Export";
1252 PWSTR Parameters
= L
"Parameters";
1253 PWSTR Linkage
= L
"Linkage";
1257 #define NPF_TAG_PATH TAG('7', 'P', 'W', 'A')
1258 Path
=ExAllocatePoolWithTag(PagedPool
, RegistryPath
->Length
+sizeof(WCHAR
), NPF_TAG_PATH
);
1261 IF_LOUD(DbgPrint("\nPacketReadRegistry: returing STATUS_INSUFFICIENT_RESOURCES\n");)
1262 return STATUS_INSUFFICIENT_RESOURCES
;
1267 RegistryPath
->Length
+sizeof(WCHAR
)
1272 RegistryPath
->Buffer
,
1273 RegistryPath
->Length
1276 IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath
->Buffer
);)
1286 // change to the linkage key
1288 //ParamTable[0].QueryRoutine = NULL;
1289 ParamTable
[0].QueryRoutine
= NPF_QueryRegistryRoutine
;
1290 ParamTable
[0].Flags
= RTL_QUERY_REGISTRY_SUBKEY
;
1291 ParamTable
[0].Name
= Linkage
;
1295 // Get the name of the mac driver we should bind to
1298 ParamTable
[1].QueryRoutine
= NPF_QueryRegistryRoutine
;
1299 ParamTable
[1].Flags
= RTL_QUERY_REGISTRY_REQUIRED
|
1300 RTL_QUERY_REGISTRY_NOEXPAND
;
1302 ParamTable
[1].Name
= Bind
;
1303 ParamTable
[1].EntryContext
= (PVOID
)MacDriverName
;
1304 ParamTable
[1].DefaultType
= REG_MULTI_SZ
;
1307 // Get the name that we should use for the driver object
1310 ParamTable
[2].QueryRoutine
= NPF_QueryRegistryRoutine
;
1311 ParamTable
[2].Flags
= RTL_QUERY_REGISTRY_REQUIRED
|
1312 RTL_QUERY_REGISTRY_NOEXPAND
;
1314 ParamTable
[2].Name
= Export
;
1315 ParamTable
[2].EntryContext
= (PVOID
)PacketDriverName
;
1316 ParamTable
[2].DefaultType
= REG_MULTI_SZ
;
1319 Status
=RtlQueryRegistryValues(
1320 RTL_REGISTRY_ABSOLUTE
,
1327 if (Status
!= STATUS_SUCCESS
) {
1328 // insert hard coded parameters here while registry on ROS is not working...
1329 IF_LOUD(DbgPrint("PacketReadRegistry() RtlQueryRegistryValues failed - returing fixed parameters\n");)
1331 *MacDriverName
= ExAllocatePool(PagedPool
, 50 * sizeof(WCHAR
));
1332 //memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
1333 memcpy(*MacDriverName
, L
"\\Device\\ne2000", 15 * sizeof(WCHAR
));
1335 *PacketDriverName
= ExAllocatePool(PagedPool
, 50 * sizeof(WCHAR
));
1336 memcpy(*PacketDriverName
, L
"\\Device\\NPF_ne2000", 19 * sizeof(WCHAR
));
1337 Status
= STATUS_SUCCESS
;
1345 //-------------------------------------------------------------------
1348 NPF_QueryRegistryRoutine(
1352 IN ULONG ValueLength
,
1354 IN PVOID EntryContext
1361 IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
1363 if (ValueType
!= REG_MULTI_SZ
) {
1365 return STATUS_OBJECT_NAME_NOT_FOUND
;
1369 #define NPF_TAG_REGBUF TAG('8', 'P', 'W', 'A')
1370 Buffer
=ExAllocatePoolWithTag(NonPagedPool
, ValueLength
, NPF_TAG_REGBUF
);
1374 return STATUS_INSUFFICIENT_RESOURCES
;
1384 *((PUCHAR
*)EntryContext
)=Buffer
;
1386 return STATUS_SUCCESS
;