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.
86 IN PDRIVER_OBJECT DriverObject,
87 IN PUNICODE_STRING RegistryPath
91 NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
92 UNICODE_STRING MacDriverName;
93 UNICODE_STRING UnicodeDeviceName;
94 PDEVICE_OBJECT DeviceObject = NULL;
95 PDEVICE_EXTENSION DeviceExtension = NULL;
96 NTSTATUS Status = STATUS_SUCCESS;
97 NTSTATUS ErrorCode = STATUS_SUCCESS;
98 NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
99 ULONG DevicesCreated=0;
102 PWSTR BindStringSave;
103 PWSTR ExportStringSave;
104 NDIS_HANDLE NdisProtocolHandle;
106 PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
107 UNICODE_STRING macName;
109 // This driver at the moment works only on single processor machines
110 if(NdisSystemProcessorCount() != 1){
111 return STATUS_IMAGE_MP_UP_MISMATCH;
114 IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");)
116 RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
119 ProtocolChar.MajorNdisVersion = 5;
121 ProtocolChar.MajorNdisVersion = 3;
123 ProtocolChar.MinorNdisVersion = 0;
125 ProtocolChar.Reserved = 0;
127 ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete;
128 ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
130 ProtocolChar.SendCompleteHandler = NPF_SendComplete;
131 ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
133 ProtocolChar.ResetCompleteHandler = NPF_ResetComplete;
134 ProtocolChar.RequestCompleteHandler = NPF_RequestComplete;
136 ProtocolChar.ReceiveHandler = NPF_tap;
138 ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete;
139 ProtocolChar.StatusHandler = NPF_Status;
140 ProtocolChar.StatusCompleteHandler = NPF_StatusComplete;
142 ProtocolChar.BindAdapterHandler = NPF_BindAdapter;
143 ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter;
144 ProtocolChar.PnPEventHandler = NPF_PowerChange;
145 ProtocolChar.ReceivePacketHandler = NULL;
147 ProtocolChar.Name = ProtoName;
149 NdisRegisterProtocol(
153 sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
155 if (Status != NDIS_STATUS_SUCCESS) {
157 IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
163 NdisAllocateSpinLock(&Opened_Instances_Lock);
165 // Set up the device driver entry points.
166 DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
167 DriverObject->MajorFunction[IRP_MJ_CLOSE] = NPF_Close;
168 DriverObject->MajorFunction[IRP_MJ_READ] = NPF_Read;
169 DriverObject->MajorFunction[IRP_MJ_WRITE] = NPF_Write;
170 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NPF_IoControl;
171 DriverObject->DriverUnload = NPF_Unload;
173 // Get the name of the Packet driver and the name of the NIC driver
174 // to bind to from the registry
175 Status=NPF_ReadRegistry(
181 if (Status != STATUS_SUCCESS) {
183 IF_LOUD(DbgPrint("Trying dynamic binding\n");)
185 bindP = getAdaptersList();
188 IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
190 tcpBindingsP = getTcpBindings();
192 if (tcpBindingsP == NULL){
193 IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
197 bindP = (WCHAR*)tcpBindingsP;
198 bindT = (WCHAR*)(tcpBindingsP->Data);
204 for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR)) {
205 RtlInitUnicodeString(&macName, bindT);
206 createDevice(DriverObject, &macName, NdisProtocolHandle);
209 return STATUS_SUCCESS;
213 BindStringSave = BindString;
214 ExportStringSave = ExportString;
218 // create a device object for each entry
220 while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) {
222 // Create a counted unicode string for both null terminated strings
224 RtlInitUnicodeString(
229 RtlInitUnicodeString(
235 // Advance to the next string of the MULTI_SZ string
237 BindString += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
239 ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
241 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,
256 if (Status != STATUS_SUCCESS) {
257 IF_LOUD(DbgPrint("NPF: IoCreateDevice() failed:\n");)
265 DeviceObject->Flags |= DO_DIRECT_IO;
266 DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
267 DeviceExtension->DeviceObject = DeviceObject;
270 // Save the the name of the MAC driver to open in the Device Extension
273 DeviceExtension->AdapterName=MacDriverName;
275 if (DevicesCreated == 1) {
277 DeviceExtension->BindString = NULL;
278 DeviceExtension->ExportString = NULL;
282 DeviceExtension->NdisProtocolHandle=NdisProtocolHandle;
287 if (DevicesCreated > 0) {
289 // Managed to create at least one device.
291 IF_LOUD(DbgPrint("NPF: Managed to create at least one device.\n");)
292 return STATUS_SUCCESS;
297 ExFreePool(BindStringSave);
298 ExFreePool(ExportStringSave);
301 IF_LOUD(DbgPrint("NPF: RegistryError: calling NdisDeregisterProtocol()\n");)
302 NdisDeregisterProtocol(
307 Status=STATUS_UNSUCCESSFUL;
313 //-------------------------------------------------------------------
315 PWCHAR getAdaptersList(void)
317 PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
318 OBJECT_ATTRIBUTES objAttrs;
323 PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, 4096, '0PWA');
325 if (DeviceNames == NULL) {
326 IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
330 InitializeObjectAttributes(&objAttrs, &AdapterListKey,
331 OBJ_CASE_INSENSITIVE, NULL, NULL);
332 status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
333 if (!NT_SUCCESS(status)) {
334 IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
337 KEY_VALUE_PARTIAL_INFORMATION valueInfo;
341 IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);)
343 // Scan the list of the devices
344 while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS) {
345 WCHAR ExportKeyName [512];
346 PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
347 UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
348 PWCHAR LinkageKeyPrefix = L"\\Linkage";
349 UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
350 NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
351 PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
352 UNICODE_STRING AdapterKeyName;
353 HANDLE ExportKeyHandle;
354 KEY_VALUE_PARTIAL_INFORMATION valueInfo;
357 RtlCopyMemory(ExportKeyName,
359 ExportKeyPrefixSize);
361 RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
363 tInfo->NameLength+2);
365 RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
367 LinkageKeyPrefixSize);
369 IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
371 RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
373 InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
374 OBJ_CASE_INSENSITIVE, NULL, NULL);
376 status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
378 if (!NT_SUCCESS(status)) {
379 DbgPrint("OpenKey Failed, %d!\n",status);
384 status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
385 KeyValuePartialInformation, &valueInfo,
386 sizeof(valueInfo), &resultLength);
388 if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
389 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
390 } else { // We know how big it needs to be.
391 ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
392 PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
393 if (valueInfoP != NULL) {
394 status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
395 KeyValuePartialInformation,
397 valueInfoLength, &resultLength);
398 if (!NT_SUCCESS(status)) {
399 IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
401 IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
402 RtlCopyMemory((PCHAR)DeviceNames+BufPos,
404 valueInfoP->DataLength);
405 BufPos+=valueInfoP->DataLength-2;
408 ExFreePool(valueInfoP);
410 IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
415 // terminate the buffer
416 DeviceNames[BufPos/2]=0;
417 DeviceNames[BufPos/2+1]=0;
419 ZwClose (ExportKeyHandle);
428 ExFreePool(DeviceNames);
434 //-------------------------------------------------------------------
436 PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
438 PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
439 OBJECT_ATTRIBUTES objAttrs;
443 InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
444 OBJ_CASE_INSENSITIVE, NULL, NULL);
445 status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
446 if (!NT_SUCCESS(status)) {
447 IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
450 KEY_VALUE_PARTIAL_INFORMATION valueInfo;
452 IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
454 status = ZwQueryValueKey(keyHandle, &bindValueName,
455 KeyValuePartialInformation, &valueInfo,
456 sizeof(valueInfo), &resultLength);
457 if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
458 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
459 } else { // We know how big it needs to be.
460 ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
461 PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
462 (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
464 if (valueInfoP != NULL) {
465 status = ZwQueryValueKey(keyHandle, &bindValueName,
466 KeyValuePartialInformation,
468 valueInfoLength, &resultLength);
470 if (!NT_SUCCESS(status)) {
471 IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
473 else if (valueInfoLength != resultLength) {
474 IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
475 "but previous len = %u\n",
476 resultLength, valueInfoLength);)
478 else if (valueInfoP->Type != REG_MULTI_SZ) {
479 IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
485 WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
486 IF_LOUD(DbgPrint("\n\nBind value:\n");)
487 for (i = 0; *dataP != UNICODE_NULL; i++) {
488 UNICODE_STRING macName;
489 RtlInitUnicodeString(&macName, dataP);
490 IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
492 (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
504 //-------------------------------------------------------------------
506 BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
507 IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
510 PDEVICE_OBJECT devObjP;
511 UNICODE_STRING deviceName;
512 BOOLEAN result = FALSE;
514 IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer);)
515 if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
516 devicePrefix.Length) < devicePrefix.Length) {
520 deviceName.Length = 0;
521 deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
522 deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
524 if (deviceName.Buffer != NULL) {
525 RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
526 RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
527 RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
528 devicePrefix.Length / sizeof(WCHAR));
530 IF_LOUD(DbgPrint("\n\nDevice name: %ws\n", deviceName.Buffer);)
532 status = IoCreateDevice(adriverObjectP, sizeof(PDEVICE_EXTENSION),
533 &deviceName, FILE_DEVICE_TRANSPORT, 0, FALSE,
536 if (NT_SUCCESS(status)) {
537 PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
539 IF_LOUD(DbgPrint("\n\nDevice created succesfully\n");)
541 devObjP->Flags |= DO_DIRECT_IO;
543 devExtP->DeviceObject = devObjP;
544 RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);
545 devExtP->BindString = NULL;
546 devExtP->ExportString = NULL;
547 devExtP->NdisProtocolHandle=aProtoHandle;
551 else IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
553 ExFreePool(deviceName.Buffer);
559 //-------------------------------------------------------------------
562 NPF_Unload(IN PDRIVER_OBJECT DriverObject)
565 PDEVICE_OBJECT DeviceObject;
566 PDEVICE_OBJECT OldDeviceObject;
567 PDEVICE_EXTENSION DeviceExtension;
569 NDIS_HANDLE NdisProtocolHandle;
572 IF_LOUD(DbgPrint("NPF: Unload\n");)
575 DeviceObject = DriverObject->DeviceObject;
577 while (DeviceObject != NULL) {
578 DeviceExtension = DeviceObject->DeviceExtension;
580 NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
581 OldDeviceObject=DeviceObject;
583 DeviceObject=DeviceObject->NextDevice;
585 IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
586 DeviceExtension->AdapterName.Buffer,
591 IoDeleteDevice(OldDeviceObject);
595 NdisDeregisterProtocol(
600 // Free the adapters names
605 //-------------------------------------------------------------------
608 NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
611 PIO_STACK_LOCATION IrpSp;
612 PLIST_ENTRY RequestListEntry;
613 PINTERNAL_REQUEST pRequest;
616 PLIST_ENTRY PacketListEntry;
621 PPACKET_OID_DATA OidData;
623 PNDIS_PACKET pPacket;
626 PUCHAR TmpBPFProgram;
628 BOOLEAN SyncWrite = FALSE;
629 struct bpf_insn *initprogram;
632 BOOLEAN IsExtendedFilter=FALSE;
634 IF_LOUD(DbgPrint("NPF: IoControl\n");)
636 IrpSp = IoGetCurrentIrpStackLocation(Irp);
637 FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
638 Open=IrpSp->FileObject->FsContext;
640 Irp->IoStatus.Status = STATUS_SUCCESS;
642 IF_LOUD(DbgPrint("NPF: Function code is %08lx buff size=%08lx %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
645 switch (FunctionCode){
647 case BIOCGSTATS: //function to get the capture stats
649 if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(INT)){
653 *(((PUINT)Irp->UserBuffer)+3) = Open->Accepted;
654 *(((PUINT)Irp->UserBuffer)) = Open->Received;
655 *(((PUINT)Irp->UserBuffer)+1) = Open->Dropped;
656 *(((PUINT)Irp->UserBuffer)+2) = 0; // Not yet supported
658 EXIT_SUCCESS(4*sizeof(INT));
662 case BIOCGEVNAME: //function to get the name of the event associated with the current instance
664 if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){
668 RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
674 case BIOCSENDPACKETSSYNC:
678 case BIOCSENDPACKETSNOSYNC:
680 WriteRes = NPF_BufferedWrite(Irp,
681 (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
682 IrpSp->Parameters.DeviceIoControl.InputBufferLength,
687 EXIT_SUCCESS(WriteRes);
690 EXIT_FAILURE(WriteRes);
696 // Free the previous buffer if it was present
697 if(Open->bpfprogram!=NULL){
698 TmpBPFProgram=Open->bpfprogram;
699 Open->bpfprogram = NULL;
700 ExFreePool(TmpBPFProgram);
703 if (Open->Filter!=NULL)
705 JIT_BPF_Filter *OldFilter=Open->Filter;
707 BPF_Destroy_JIT_Filter(OldFilter);
710 // Get the pointer to the new program
711 prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
714 IF_LOUD(DbgPrint("0001");)
719 insns=(IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
721 //count the number of operative instructions
722 for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
724 IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
726 if (((struct bpf_insn*)prog)[cnt].code==BPF_SEPARATION && (insns-cnt-1)!=0)
728 IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
730 IsExtendedFilter=TRUE;
732 initprogram=&((struct bpf_insn*)prog)[cnt+1];
734 if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
737 IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
743 //the NPF processor has been initialized, we have to validate the operative instructions
746 if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
748 IF_LOUD(DbgPrint("Error validating program");)
749 //FIXME: the machine has been initialized(?), but the operative code is wrong.
750 //we have to reset the machine!
751 //something like: reallocate the mem_ex, and reset the tme_core
755 // Allocate the memory to contain the new filter program
756 // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
757 TmpBPFProgram=(PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), '4PWA');
758 if (TmpBPFProgram==NULL){
759 IF_LOUD(DbgPrint("Error - No memory for filter");)
764 //copy the program in the new buffer
765 RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
766 Open->bpfprogram=TmpBPFProgram;
768 // Create the new JIT filter function
770 if(!IsExtendedFilter)
771 if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt))
774 IF_LOUD(DbgPrint("Error jittering filter");)
785 EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
789 case BIOCSMODE: //set the capture mode
791 mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
793 if(mode == MODE_CAPT){
794 Open->mode=MODE_CAPT;
798 else if (mode==MODE_MON){
804 if(mode & MODE_STAT){
805 Open->mode = MODE_STAT;
806 Open->Nbytes.QuadPart=0;
807 Open->Npackets.QuadPart=0;
809 if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart=-10000000;
813 if(mode & MODE_DUMP){
815 Open->mode |= MODE_DUMP;
816 Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
826 case BIOCSETDUMPFILENAME:
828 if(Open->mode & MODE_DUMP)
831 // Close current dump file
832 if(Open->DumpFileHandle != NULL){
833 NPF_CloseDumpFile(Open);
834 Open->DumpFileHandle = NULL;
837 if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
841 // Allocate the buffer that will contain the string
842 DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA');
843 if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
844 IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
849 RtlCopyBytes((PVOID)DumpNameBuff,
850 Irp->AssociatedIrp.SystemBuffer,
851 IrpSp->Parameters.DeviceIoControl.InputBufferLength);
853 // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
854 ((SHORT*)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
856 // Create the unicode string
857 RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
859 IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
860 Open->DumpFileName.Buffer,
861 IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
863 // Try to create the file
864 if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
865 NT_SUCCESS( NPF_StartDump(Open))){
875 case BIOCSETDUMPLIMITS:
877 Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
878 Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
880 IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
886 case BIOCISDUMPENDED:
887 if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4){
891 *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
897 case BIOCSETBUFFERSIZE:
899 // Get the number of bytes to allocate
900 dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
902 // Free the old buffer
903 tpointer = Open->Buffer;
904 if(tpointer != NULL){
907 ExFreePool(tpointer);
909 // Allocate the new buffer
911 tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
912 if (tpointer==NULL) {
922 Open->Buffer = tpointer;
927 Open->BufSize = (UINT)dim;
932 case BIOCSRTIMEOUT: //set the timeout on the read calls
934 timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
936 Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
938 Open->TimeOut.QuadPart=(LONGLONG)timeout;
939 Open->TimeOut.QuadPart*=10000;
940 Open->TimeOut.QuadPart=-Open->TimeOut.QuadPart;
943 //IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
944 EXIT_SUCCESS(timeout);
948 case BIOCSWRITEREP: //set the writes repetition number
950 Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
952 EXIT_SUCCESS(Open->Nwrites);
956 case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
958 Open->MinToCopy = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
960 EXIT_SUCCESS(Open->MinToCopy);
964 case IOCTL_PROTOCOL_RESET:
966 IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
968 IoMarkIrpPending(Irp);
969 Irp->IoStatus.Status = STATUS_SUCCESS;
971 ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
972 NdisReset(&Status,Open->AdapterHandle);
973 if (Status != NDIS_STATUS_PENDING) {
974 IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
975 NPF_ResetComplete(Open,Status);
984 // Extract a request from the list of free ones
985 RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
986 if (RequestListEntry == NULL)
991 pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
995 // See if it is an Ndis request
997 OidData=Irp->AssociatedIrp.SystemBuffer;
999 if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
1001 (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
1003 (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
1005 (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
1007 IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
1010 // The buffer is valid
1012 if (FunctionCode == BIOCSETOID){
1014 pRequest->Request.RequestType=NdisRequestSetInformation;
1015 pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
1017 pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
1018 pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
1020 pRequest->Request.RequestType=NdisRequestQueryInformation;
1021 pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
1023 pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
1024 pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
1028 NdisResetEvent(&Open->IOEvent);
1030 // submit the request
1034 Open->AdapterHandle,
1042 Status=NDIS_STATUS_FAILURE;
1043 pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
1044 pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
1048 if (Status != NDIS_STATUS_PENDING) {
1049 IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
1051 NPF_RequestComplete(Open, &pRequest->Request, Status);
1056 NdisWaitEvent(&Open->IOEvent, 5000);
1058 return(Open->IOStatus);
1071 //-------------------------------------------------------------------
1074 NPF_RequestComplete(
1075 IN NDIS_HANDLE ProtocolBindingContext,
1076 IN PNDIS_REQUEST NdisRequest,
1077 IN NDIS_STATUS Status
1081 POPEN_INSTANCE Open;
1082 PIO_STACK_LOCATION IrpSp;
1084 PINTERNAL_REQUEST pRequest;
1088 PPACKET_OID_DATA OidData;
1090 IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
1092 Open= (POPEN_INSTANCE)ProtocolBindingContext;
1094 pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
1099 // Put the request in the list of the free ones
1100 ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
1105 IrpSp = IoGetCurrentIrpStackLocation(Irp);
1107 FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
1109 OidData=Irp->AssociatedIrp.SystemBuffer;
1111 if (FunctionCode == BIOCSETOID) {
1113 OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
1117 if (FunctionCode == BIOCQUERYOID) {
1119 OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
1121 IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
1126 Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
1128 IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
1130 ExInterlockedInsertTailList(
1132 &pRequest->ListElement,
1133 &Open->RequestSpinLock);
1135 Irp->IoStatus.Status = Status;
1137 Open->IOStatus = Status;
1139 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1141 // Unlock the IOCTL call
1142 NdisSetEvent(&Open->IOEvent);
1149 //-------------------------------------------------------------------
1153 IN NDIS_HANDLE ProtocolBindingContext,
1154 IN NDIS_STATUS Status,
1155 IN PVOID StatusBuffer,
1156 IN UINT StatusBufferSize
1161 IF_LOUD(DbgPrint("NPF: Status Indication\n");)
1167 //-------------------------------------------------------------------
1171 IN NDIS_HANDLE ProtocolBindingContext
1176 IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
1182 //-------------------------------------------------------------------
1186 IN PWSTR *MacDriverName,
1187 IN PWSTR *PacketDriverName,
1188 IN PUNICODE_STRING RegistryPath
1194 RTL_QUERY_REGISTRY_TABLE ParamTable[4];
1196 PWSTR Bind = L"Bind";
1197 PWSTR Export = L"Export";
1198 PWSTR Parameters = L"Parameters";
1199 PWSTR Linkage = L"Linkage";
1203 Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA');
1206 IF_LOUD(DbgPrint("\nPacketReadRegistry: returing STATUS_INSUFFICIENT_RESOURCES\n");)
1207 return STATUS_INSUFFICIENT_RESOURCES;
1212 RegistryPath->Length+sizeof(WCHAR)
1217 RegistryPath->Buffer,
1218 RegistryPath->Length
1221 IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
1231 // change to the linkage key
1233 //ParamTable[0].QueryRoutine = NULL;
1234 ParamTable[0].QueryRoutine = NPF_QueryRegistryRoutine;
1235 ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
1236 ParamTable[0].Name = Linkage;
1240 // Get the name of the mac driver we should bind to
1243 ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
1244 ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
1245 RTL_QUERY_REGISTRY_NOEXPAND;
1247 ParamTable[1].Name = Bind;
1248 ParamTable[1].EntryContext = (PVOID)MacDriverName;
1249 ParamTable[1].DefaultType = REG_MULTI_SZ;
1252 // Get the name that we should use for the driver object
1255 ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
1256 ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
1257 RTL_QUERY_REGISTRY_NOEXPAND;
1259 ParamTable[2].Name = Export;
1260 ParamTable[2].EntryContext = (PVOID)PacketDriverName;
1261 ParamTable[2].DefaultType = REG_MULTI_SZ;
1264 Status=RtlQueryRegistryValues(
1265 RTL_REGISTRY_ABSOLUTE,
1272 if (Status != STATUS_SUCCESS) {
1273 // insert hard coded parameters here while registry on ROS is not working...
1274 IF_LOUD(DbgPrint("PacketReadRegistry() RtlQueryRegistryValues failed - returing fixed parameters\n");)
1276 *MacDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
1277 //memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
1278 memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
1280 *PacketDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
1281 memcpy(*PacketDriverName, L"\\Device\\NPF_ne2000", 19 * sizeof(WCHAR));
1282 Status = STATUS_SUCCESS;
1290 //-------------------------------------------------------------------
1293 NPF_QueryRegistryRoutine(
1297 IN ULONG ValueLength,
1299 IN PVOID EntryContext
1306 IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
1308 if (ValueType != REG_MULTI_SZ) {
1310 return STATUS_OBJECT_NAME_NOT_FOUND;
1314 Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA');
1318 return STATUS_INSUFFICIENT_RESOURCES;
1328 *((PUCHAR *)EntryContext)=Buffer;
1330 return STATUS_SUCCESS;