庖丁解牛---winpcap源码彻底解密系列的续集(7)

2024-01-13 01:48

本文主要是介绍庖丁解牛---winpcap源码彻底解密系列的续集(7),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

DeviceIoControl对应npf.sys中的NPF_IoControl函数;

 

NTSTATUS NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)

{

    POPEN_INSTANCE      Open;

    PIO_STACK_LOCATION  IrpSp;

    PLIST_ENTRY         RequestListEntry;

    PINTERNAL_REQUEST   pRequest;

    ULONG               FunctionCode;

    NDIS_STATUS          Status;

         ULONG                                Information = 0;

         PLIST_ENTRY         PacketListEntry;

         UINT                                     i;

         PUCHAR                              tpointer;

         ULONG                                dim,timeout;

         struct bpf_insn*         NewBpfProgram;

         PPACKET_OID_DATA    OidData;

         int                                          *StatsBuf;

    PNDIS_PACKET        pPacket;

         ULONG                                mode;

         PWSTR                                DumpNameBuff;

         PUCHAR                              TmpBPFProgram;

         INT                                        WriteRes;

         BOOLEAN                                     SyncWrite = FALSE;

         struct bpf_insn          *initprogram;

         ULONG                                insns;

         ULONG                                cnt;

         BOOLEAN                                     IsExtendedFilter=FALSE;

         ULONG                                StringLength;

         ULONG                                NeededBytes;

         BOOLEAN                                     Flag;

         PUINT                                   pStats;

         ULONG                                StatsLength;

 

         HANDLE                              hUserEvent;

         PKEVENT                                      pKernelEvent;

#ifdef _AMD64_

    VOID*POINTER_32            hUserEvent32Bit;

#endif //_AMD64_

         PMDL                                    mdl;

 

         TRACE_ENTER();

 

         IrpSp = IoGetCurrentIrpStackLocation(Irp);

    FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;

    Open=IrpSp->FileObject->FsContext;

 

         if (NPF_StartUsingOpenInstance(Open) == FALSE)

         {

                   //

                   // an IRP_MJ_CLEANUP was received, just fail the request

                   //

                   Irp->IoStatus.Information = 0;

                   Irp->IoStatus.Status = STATUS_CANCELLED;

                   IoCompleteRequest(Irp, IO_NO_INCREMENT);

                   TRACE_EXIT();

                   return STATUS_CANCELLED;

         }

 

    Irp->IoStatus.Status = STATUS_SUCCESS;

 

         TRACE_MESSAGE3(PACKET_DEBUG_LOUD,

                   "Function code is %08lx Input size=%08lx Output size %08lx",

                   FunctionCode,

                   IrpSp->Parameters.DeviceIoControl.InputBufferLength,

                   IrpSp->Parameters.DeviceIoControl.OutputBufferLength);

 

         switch (FunctionCode){

                  

         case BIOCGSTATS: //function to get the capture stats

 

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCGSTATS");

 

                   StatsLength = 4*sizeof(UINT);

                   if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < StatsLength)

                   {                          

                            SET_FAILURE_BUFFER_SMALL();

                            break;

                  }

 

                   if (Irp->UserBuffer == NULL)

                   {

                            SET_FAILURE_UNSUCCESSFUL();

                            break;

                   }

 

                   //

                   // temp fix to a GIANT bug from LD. The CTL code has been defined as METHOD_NEITHER, so it

                   // might well be a dangling pointer. We need to probe and lock the address.

                   //

 

                   mdl = NULL;

                   pStats = NULL;

 

                   __try

                   {

                            mdl = IoAllocateMdl(

                                     Irp->UserBuffer, 

                                     StatsLength,

                                     FALSE,

                                     TRUE,

                                     NULL);

 

                            if (mdl == NULL)

                            {

                                     SET_FAILURE_UNSUCCESSFUL();

                                     break;

                            }

 

                            MmProbeAndLockPages(

                                     mdl,

                                     UserMode,

                                     IoWriteAccess);

 

                            pStats = (PUINT)(Irp->UserBuffer);

                   }

                   __except(GetExceptionCode() == STATUS_ACCESS_VIOLATION)

                   {

                            pStats = NULL;

                   }

 

                   if (pStats == NULL)

                   {

                            if (mdl != NULL)

                            {

                                     IoFreeMdl(mdl);

                            }

 

                            SET_FAILURE_UNSUCCESSFUL();

                            break;

                   }

 

                   pStats[3] = 0;

                   pStats[0] = 0;

                   pStats[1] = 0;

                   pStats[2] = 0;              // Not yet supported

 

                   for(i = 0 ; i < g_NCpu ; i++)

                   {

 

                            pStats[3] += Open->CpuData[i].Accepted;

                            pStats[0] += Open->CpuData[i].Received;

                            pStats[1] += Open->CpuData[i].Dropped;

                            pStats[2] += 0;           // Not yet supported

                   }

                  

                   MmUnlockPages(mdl);

                   IoFreeMdl(mdl);

 

                   SET_RESULT_SUCCESS(StatsLength);

                  

                   break;

                  

         case BIOCGEVNAME: //function to get the name of the event associated with the current instance

                  

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCGEVNAME");

 

                   //

                   // Since 20060405, the event handling has been changed:

                   // we no longer use named events, instead the user level app creates an event,

                   // and passes it back to the kernel, that references it (ObReferenceObjectByHandle), and

                   // signals it.

                   // For the time being, we still leave this ioctl code here, and we simply fail.

                   //

                   SET_FAILURE_INVALID_REQUEST();

                   break;

 

         case BIOCSENDPACKETSSYNC:

 

                   SyncWrite = TRUE;

 

         case BIOCSENDPACKETSNOSYNC:

 

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSENDPACKETSNOSYNC");

                  

                   NdisAcquireSpinLock(&Open->WriteLock);

                   if(Open->WriteInProgress)

                   {

                            NdisReleaseSpinLock(&Open->WriteLock);

                            //

                            // Another write operation is currently in progress

                            //

                            SET_FAILURE_UNSUCCESSFUL();

                            break;

                   }

                   else

                   {

                            Open->WriteInProgress = TRUE;

                   }

                   NdisReleaseSpinLock(&Open->WriteLock);

                  

                   WriteRes = NPF_BufferedWrite(Irp,

                            (PUCHAR)Irp->AssociatedIrp.SystemBuffer,

                            IrpSp->Parameters.DeviceIoControl.InputBufferLength,

                            SyncWrite);

 

                   NdisAcquireSpinLock(&Open->WriteLock);

                   Open->WriteInProgress = FALSE;

                   NdisReleaseSpinLock(&Open->WriteLock);

 

                   if( WriteRes != -1)

                   {

                            SET_RESULT_SUCCESS(WriteRes);

                   }

                   else

                   {

                            SET_FAILURE_UNSUCCESSFUL();

                   }

                   break;

 

         case BIOCSETF: 

 

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETF");

 

                   //

                   // Get the pointer to the new program

                   //

                   NewBpfProgram = (struct bpf_insn*)Irp->AssociatedIrp.SystemBuffer;

                  

                   if(NewBpfProgram == NULL)

                   {

                            SET_FAILURE_BUFFER_SMALL();

                            break;

                   }

                  

                   //

                   // Lock the machine. After this call we are at DISPATCH level

                   //

                   NdisAcquireSpinLock(&Open->MachineLock);

 

                   do

                   {

 

                            // Free the previous buffer if it was present

                            if(Open->bpfprogram != NULL)

                            {

                                     TmpBPFProgram = Open->bpfprogram;

                                     Open->bpfprogram = NULL;

                                     ExFreePool(TmpBPFProgram);

                            }

                  

//

// Jitted filters are supported on x86 (32bit) only

//

#ifdef _X86_

                            if (Open->Filter != NULL)

                            {

                                     BPF_Destroy_JIT_Filter(Open->Filter);

                                     Open->Filter = NULL;

                            }

#endif // _X86_

 

                            insns = (IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);

                  

                            //count the number of operative instructions

                            for (cnt = 0 ; (cnt < insns) &&(NewBpfProgram[cnt].code != BPF_SEPARATION); cnt++);

                  

                            TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Operative instructions=%u", cnt);

 

#ifdef HAVE_BUGGY_TME_SUPPORT

                            if ( (cnt != insns) && (insns != cnt+1) && (NewBpfProgram[cnt].code == BPF_SEPARATION))

                            {

                                     TRACE_MESSAGE1(PACKET_DEBUG_LOUD,"Initialization instructions = %u",insns-cnt-1);

                  

                                     IsExtendedFilter = TRUE;

 

                                     initprogram = &NewBpfProgram[cnt+1];

                                    

                                     if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)

                                     {

                                    

                                               TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error initializing NPF machine (bpf_filter_init)");

                                              

                                               SET_FAILURE_INVALID_REQUEST();

                                               break;

                                     }

                            }

#else  // HAVE_BUGGY_TME_SUPPORT

                            if ( cnt != insns)

                            {

                                     TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error installing the BPF filter. The filter contains TME extensions,"

                                               " not supported on 64bit platforms.");

 

                                     SET_FAILURE_INVALID_REQUEST();

                                     break;

                            }

#endif // HAVE_BUGGY_TME_SUPPORT

 

                            //the NPF processor has been initialized, we have to validate the operative instructions

                            insns = cnt;

                  

                            //NOTE: the validation code checks for TME instructions, and fails if a TME instruction is

                            //encountered on 64 bit machines

#ifdef HAVE_BUGGY_TME_SUPPORT

                            if(bpf_validate(NewBpfProgram, cnt, Open->mem_ex.size) == 0)

#else //HAVE_BUGGY_TME_SUPPORT

                            if(bpf_validate(NewBpfProgram, cnt) == 0)

#endif //HAVE_BUGGY_TME_SUPPORT

                            {

                                     TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error validating program");

                                     //FIXME: the machine has been initialized(?), but the operative code is wrong.

                                     //we have to reset the machine!

                                     //something like: reallocate the mem_ex, and reset the tme_core

                                     SET_FAILURE_INVALID_REQUEST();

                                     break;

                            }

                  

                            // Allocate the memory to contain the new filter program

                            // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()

                            TmpBPFProgram = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), '4PWA');

                            if (TmpBPFProgram == NULL)

                            {

                                     TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error - No memory for filter");

                                     // no memory

                                    

                                     SET_FAILURE_NOMEM();

                                     break;

                            }

                  

                            //

                            // At the moment the JIT compiler works on x86 (32 bit) only

                            //

#ifdef _X86_

                            // Create the new JIT filter function

                            if(!IsExtendedFilter)

                            {

                                     if((Open->Filter = BPF_jitter(NewBpfProgram, cnt)) == NULL)

                                     {

                                               TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error jittering filter");

                                              

                                               ExFreePool(TmpBPFProgram);

 

                                               SET_FAILURE_UNSUCCESSFUL();

                                               break;

                                     }

                            }

#endif //_X86_

 

                            //copy the program in the new buffer

                            RtlCopyMemory(TmpBPFProgram,NewBpfProgram,cnt*sizeof(struct bpf_insn));

                            Open->bpfprogram = TmpBPFProgram;

 

                            SET_RESULT_SUCCESS(0);

                   }

                   while(FALSE);

 

                   //

                   // release the machine lock and then reset the buffer

                   //

                   NdisReleaseSpinLock(&Open->MachineLock);

 

                   NPF_ResetBufferContents(Open);

 

                   break;                

                  

         case BIOCSMODE:  //set the capture mode

 

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSMODE");

 

                   if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))

                   {                          

                            SET_FAILURE_BUFFER_SMALL();

                            break;

                   }

 

                   mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);

                  

///kernel dump does not work at the moment//

                   if (mode & MODE_DUMP)

                   {                          

                            SET_FAILURE_INVALID_REQUEST();

                            break;

                   }

///kernel dump does not work at the moment//

 

                   if(mode == MODE_CAPT)

                   {

                            Open->mode = MODE_CAPT;

                           

                            SET_RESULT_SUCCESS(0);

                            break;

                   }

                  else if (mode == MODE_MON)

                   {

                            //

                            // The MONITOR_MODE (aka TME extensions) is not supported on

                            // 64 bit architectures

                            //

 

#ifdef HAVE_BUGGY_TME_SUPPORT

                            Open->mode = MODE_MON;

                            SET_RESULT_SUCCESS(0);

#else // HAVE_BUGGY_TME_SUPPORT

                            SET_FAILURE_INVALID_REQUEST();

#endif // HAVE_BUGGY_TME_SUPPORT

 

                            break;

                   }       

                   else{

                            if(mode & MODE_STAT){

                                     Open->mode = MODE_STAT;

                                     NdisAcquireSpinLock(&Open->CountersLock);

                                     Open->Nbytes.QuadPart = 0;

                                     Open->Npackets.QuadPart = 0;

                                     NdisReleaseSpinLock(&Open->CountersLock);

                                    

                                     if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart = -10000000;

                                    

                            }

                           

                            if(mode & MODE_DUMP){

                                    

                                     Open->mode |= MODE_DUMP;

//                                   Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;

                                    

                            }       

 

                            SET_RESULT_SUCCESS(0);

                            break;

                   }

                  

                   SET_FAILURE_INVALID_REQUEST();

                  

                   break;

 

         case BIOCSETDUMPFILENAME:

 

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETDUMPFILENAME");

 

///kernel dump does not work at the moment//

                   SET_FAILURE_INVALID_REQUEST();

                   break;

///kernel dump does not work at the moment//

 

                   //if(Open->mode & MODE_DUMP)

                   //{

                   //      

                   //       // Close current dump file

                   //       if(Open->DumpFileHandle != NULL)

                   //       {

                   //                 NPF_CloseDumpFile(Open);

                   //                 Open->DumpFileHandle = NULL;

                   //       }

                   //      

                   //       if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){

                   //                 EXIT_FAILURE(0);

                   //       }

                   //      

                   //       // Allocate the buffer that will contain the string

                   //       DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA');

                   //       if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){

                   //                 IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)

                   //                          EXIT_FAILURE(0);

                   //       }

                   //      

                  //       // Copy the buffer

                   //       RtlCopyBytes((PVOID)DumpNameBuff,

                   //                 Irp->AssociatedIrp.SystemBuffer,

                   //                 IrpSp->Parameters.DeviceIoControl.InputBufferLength);

                   //      

                   //       // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system

                   //       ((PSHORT)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;

                   //      

                   //       // Create the unicode string

                   //       RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);

                   //      

                   //       IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",

                   //                 Open->DumpFileName.Buffer,

                   //                 IrpSp->Parameters.DeviceIoControl.InputBufferLength);)

                   //                

                   //       // Try to create the file

                   //       if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&

                   //                 NT_SUCCESS( NPF_StartDump(Open)))

                   //       {

                   //                 EXIT_SUCCESS(0);

                   //       }

                   //}

                   //

                   //EXIT_FAILURE(0);

                   //

                   //break;

                                    

         case BIOCSETDUMPLIMITS:

 

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETDUMPLIMITS");

 

///kernel dump does not work at the moment//

                   SET_FAILURE_INVALID_REQUEST();

                   break;

///kernel dump does not work at the moment//

 

                   //if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2*sizeof(ULONG))

                   //{

                   //       EXIT_FAILURE(0);

                   //}

                   //

                   //Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;

                   //Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);

                   //

                   //IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)

                   //

                   //EXIT_SUCCESS(0);

                   //

                   //break;

 

         case BIOCISDUMPENDED:

 

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCISDUMPENDED");

 

///kernel dump does not work at the moment//

                   SET_FAILURE_INVALID_REQUEST();

                   break;

///kernel dump does not work at the moment//

 

                   //if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT))

                   //{                        

                   //       EXIT_FAILURE(0);

                   //}

 

                   //*((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;

 

                   //EXIT_SUCCESS(4);

 

                   //break;

 

         case BIOCISETLOBBEH:

 

                   if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(INT))

                   {

                            SET_FAILURE_BUFFER_SMALL();

                            break;

                   }

 

#ifdef __NPF_NT4__

 

                   // NT4 doesn't support loopback inhibition / activation

                   SET_FAILURE_INVALID_REQUEST();

                   break;

 

#else //not __NPF_NT4__

                   //

                   // win2000/xp/2003/vista

                   //

                   if(*(PINT)Irp->AssociatedIrp.SystemBuffer == NPF_DISABLE_LOOPBACK)

                   {

                            Open->SkipSentPackets = TRUE;

                                    

                            //

                            // Reset the capture buffers, since they could contain loopbacked packets

                            //

 

                            NPF_ResetBufferContents(Open);

 

                            SET_RESULT_SUCCESS(0);

                            break;

 

                   }

                   else

                   if(*(PINT)Irp->AssociatedIrp.SystemBuffer == NPF_ENABLE_LOOPBACK)

                   {

                            Open->SkipSentPackets = FALSE;

 

                            SET_RESULT_SUCCESS(0);

                            break;

                   }

                   else

                   {

                            // Unknown operation

                            SET_FAILURE_INVALID_REQUEST();

                            break;

                   }

 

#endif // !__NPF_NT4__

                   break;

 

         case BIOCSETEVENTHANDLE:

                  

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETEVENTHANDLE");

                  

#ifdef _AMD64_

                   if (IoIs32bitProcess(Irp))

                   {

            //

                            // validate the input

                            //

                            if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof (hUserEvent32Bit))

                            {

                                     SET_FAILURE_INVALID_REQUEST();

                                     break;

                            }

 

                            hUserEvent32Bit = *(VOID*POINTER_32*)Irp->AssociatedIrp.SystemBuffer;

                            hUserEvent = hUserEvent32Bit;

                   }

                   else

#endif //_AMD64_

                   {

            //

                            // validate the input

                            //

                            if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof (hUserEvent))

                            {

                                     SET_FAILURE_INVALID_REQUEST();

                                     break;

                            }

        

                            hUserEvent = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;

                   }

 

                   //

                   // NT4 doesn't seem to have EVENT_MODIFY_STATE, so on NT4 we request a wider set

                   // of privileges for the event handle

                   //

#ifdef __NPF_NT4__

                   Status = ObReferenceObjectByHandle(hUserEvent,

                            OBJECT_TYPE_ALL_ACCESS, *ExEventObjectType, Irp->RequestorMode,

                            (PVOID*) &pKernelEvent, NULL);

#else   //__NPF_NT4__

                   Status = ObReferenceObjectByHandle(hUserEvent,

                            EVENT_MODIFY_STATE, *ExEventObjectType, Irp->RequestorMode,

                            (PVOID*) &pKernelEvent, NULL);

#endif  //__NPF_NT4__          

 

                   if (!NT_SUCCESS(Status))

                   {

                            // Status = ??? already set

                            Information = 0;

                            break;

                   }

 

 

                   //

                   // NT4 does not have InterlockedCompareExchangePointer

                   // InterlockedCompareExchange on NT4 has the same prototype of InterlockedCompareExchange

                   // on NT5x, so we use this one.

                   //

#ifdef __NPF_NT4__

                   if (InterlockedCompareExchange(&Open->ReadEvent, pKernelEvent, NULL) != NULL)

#else

                   if (InterlockedCompareExchangePointer(&Open->ReadEvent, pKernelEvent, NULL) != NULL)

#endif

                   {

                            //

                            // dereference the new pointer

                            //

                           

                            ObDereferenceObject(pKernelEvent);

                            SET_FAILURE_INVALID_REQUEST();

                            break;

                   }

 

                   KeResetEvent(Open->ReadEvent);

 

                   SET_RESULT_SUCCESS(0);

                   break;

 

         case BIOCSETBUFFERSIZE:

                  

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETBUFFERSIZE");

 

 

                   if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))

                   {                          

                            SET_FAILURE_BUFFER_SMALL();

                            break;

                   }

 

                   // Get the number of bytes to allocate

                   dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);

 

                   if (dim / g_NCpu < sizeof(struct PacketHeader))

                   {

                            dim = 0;

                   }

                   else

                   {

                            tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');

                            if (tpointer == NULL)

                            {

                                     // no memory

                                     SET_FAILURE_NOMEM();

                                     break;

                            }

                   }

 

                   //

                   // acquire the locks for all the buffers

                   //

                   for (i = 0; i < g_NCpu ; i++)

                   {

#pragma prefast(suppress:8103, "There's no Spinlock leak here, as it's released some lines below.")

                            NdisAcquireSpinLock(&Open->CpuData[i].BufferLock);

                   }

 

                   //

                   // free the old buffer, if any

                   //

                   if (Open->CpuData[0].Buffer != NULL)

                   {

                            ExFreePool(Open->CpuData[0].Buffer);

                   }

 

                   for (i = 0 ; i < g_NCpu ; i++)

                   {

                            if (dim > 0)

                                     Open->CpuData[i].Buffer=(PUCHAR)tpointer + (dim/g_NCpu)*i;

                            else

                                     Open->CpuData[i].Buffer = NULL;

                            Open->CpuData[i].Free = dim/g_NCpu;

                            Open->CpuData[i].P = 0;

                            Open->CpuData[i].C = 0;

                            Open->CpuData[i].Accepted = 0;

                            Open->CpuData[i].Dropped = 0;

                            Open->CpuData[i].Received = 0;

                   }

 

                   Open->ReaderSN=0;

                   Open->WriterSN=0;

 

                   Open->Size = dim/g_NCpu;

 

                   //

                   // acquire the locks for all the buffers

                   //

                   i = g_NCpu;

 

                   do

                   {

                            i--;

 

#pragma prefast(suppress:8107, "There's no Spinlock leak here, as it's acquired some lines above.")

                            NdisReleaseSpinLock(&Open->CpuData[i].BufferLock);

                   }while(i != 0);

 

                   SET_RESULT_SUCCESS(0);

                   break;

                  

         case BIOCSRTIMEOUT: //set the timeout on the read calls

                  

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSRTIMEOUT");

 

                   if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))

                   {                          

                            SET_FAILURE_BUFFER_SMALL();

                            break;

                   }

 

                   timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);

                   if(timeout == (ULONG)-1)

                            Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;

                   else

                   {

                            Open->TimeOut.QuadPart = (LONGLONG)timeout;

                            Open->TimeOut.QuadPart *= 10000;

                            Open->TimeOut.QuadPart = -Open->TimeOut.QuadPart;

                   }

 

                   TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Read timeout set to %I64d",Open->TimeOut.QuadPart);

                  

                   SET_RESULT_SUCCESS(0);          

                   break;

                  

         case BIOCSWRITEREP: //set the writes repetition number

                  

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSWRITEREP");

 

                   if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))

                   {                          

                            SET_FAILURE_BUFFER_SMALL();

                            break;

                   }

 

                   Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);

 

                   SET_RESULT_SUCCESS(0);

                   break;

 

         case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application

 

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSMINTOCOPY");

 

                   if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))

                   {                          

                            SET_FAILURE_BUFFER_SMALL();

                            break;

                   }

 

                   Open->MinToCopy = (*((PULONG)Irp->AssociatedIrp.SystemBuffer))/g_NCpu;  //An hack to make the NCPU-buffers behave like a larger one

                  

                   SET_RESULT_SUCCESS(0);

                   break;

                  

//       case IOCTL_PROTOCOL_RESET:

//

//                 TRACE_MESSAGE(PACKET_DEBUG_LOUD, "IOCTL_PROTOCOL_RESET");

//

//                 IoMarkIrpPending(Irp);

//                 Irp->IoStatus.Status = STATUS_SUCCESS;

//

//                 ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);

//      NdisReset(&Status,Open->AdapterHandle);

//      if (Status != NDIS_STATUS_PENDING)

//        {

//            IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)

//                                   NPF_ResetComplete(Open,Status);

//        }

//                

//                 break;

                  

         case BIOCSETOID:

         case BIOCQUERYOID:

                  

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETOID - BIOCQUERYOID");

 

                   //

                   // gain ownership of the Ndis Handle

                   //

                   if (NPF_StartUsingBinding(Open) == FALSE)

                   {

                            //

                            // MAC unbindind or unbound

                            //

                            SET_FAILURE_INVALID_REQUEST();

                            break;

                   }

 

 

                   // Extract a request from the list of free ones

                   RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);

                   if (RequestListEntry == NULL)

                   {

                            //

                            // Release ownership of the Ndis Handle

                            //

                            NPF_StopUsingBinding(Open);

 

                            SET_FAILURE_NOMEM();

                            break;

                   }

 

                   pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);

 

                   //

        //  See if it is an Ndis request

        //

        OidData=Irp->AssociatedIrp.SystemBuffer;

                  

        if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)

            &&

            (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))

            &&

            (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {

                           

            TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "BIOCSETOID|BIOCQUERYOID Request: Oid=%08lx, Length=%08lx",OidData->Oid,OidData->Length);

                                    

                                     //

                                     //  The buffer is valid

                                     //

                                     if (FunctionCode == BIOCSETOID){

                                              

                                               pRequest->Request.RequestType=NdisRequestSetInformation;

                                               pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;

                                              

                                               pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;

                                               pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;

                                              

                                              

                                     }

                                     else{

                                                                          

                                               pRequest->Request.RequestType=NdisRequestQueryInformation;

                                               pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;

                                              

                                               pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;

                                               pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;

                                              

                                     }

 

                                     NdisResetEvent(&pRequest->InternalRequestCompletedEvent);

                                    

                                     //

                                     //  submit the request

                                     //

                                     NdisRequest(

                                               &Status,

                                               Open->AdapterHandle,

                                               &pRequest->Request

                                               );

                                    

        } else {

                            //

                            // Release ownership of the Ndis Handle

                            //

                            NPF_StopUsingBinding(Open);

 

            //

            //  buffer too small

            //

                            SET_FAILURE_BUFFER_SMALL();

                            break;

        }

                  

        if (Status == NDIS_STATUS_PENDING)

                   {

                            NdisWaitEvent(&pRequest->InternalRequestCompletedEvent, 0);

                            Status = pRequest->RequestStatus;

                   }

 

                   //

                   // Release ownership of the Ndis Handle

                   //

                   NPF_StopUsingBinding(Open);

 

                   //

                   // Complete the request

                   //

                   if (FunctionCode == BIOCSETOID)

                   {

                            OidData->Length = pRequest->Request.DATA.SET_INFORMATION.BytesRead;

                            TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "BIOCSETOID completed, BytesRead = %u",OidData->Length);

                   }

                   else

                   {

                            if (FunctionCode == BIOCQUERYOID)

                            {

                                     OidData->Length = pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;

 

                                     if (Status == NDIS_STATUS_SUCCESS)

                                     {

                                               //

                                               // check for the stupid bug of the Nortel driver ipsecw2k.sys v. 4.10.0.0 that doesn't set the BytesWritten correctly

                                               // The driver is the one shipped with Nortel client Contivity VPN Client V04_65.18, and the MD5 for the buggy (unsigned) driver

                                               // is 3c2ff8886976214959db7d7ffaefe724 *ipsecw2k.sys (there are multiple copies of this binary with the same exact version info!)

                                               //

                                               // The (certified) driver shipped with Nortel client Contivity VPN Client V04_65.320 doesn't seem affected by the bug.

                                               //

                                               if (pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten > pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength)

                                               {

                                                        TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "Bogus return from NdisRequest (query): Bytes Written (%u) > InfoBufferLength (%u)!!",

                                                                 pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten,

                                                                 pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength);

 

                                                        Status = NDIS_STATUS_INVALID_DATA;

                                               }

                                     }

 

                                     TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "BIOCQUERYOID completed, BytesWritten = %u",OidData->Length);

                            }

                   }

 

 

                   ExInterlockedInsertTailList(

                            &Open->RequestList,

                            &pRequest->ListElement,

                            &Open->RequestSpinLock);

 

                   if (Status == NDIS_STATUS_SUCCESS)

                   {

                            SET_RESULT_SUCCESS(sizeof(PACKET_OID_DATA) - 1 + OidData->Length);

                   }

                   else

                   {

                            SET_FAILURE_INVALID_REQUEST();

                   }

 

                   break;

                  

                  

         default:

                  

                   TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Unknown IOCTL code");

                   SET_FAILURE_INVALID_REQUEST();

                   break;

         }

        

 

         //

         // release the Open structure

         //

         NPF_StopUsingOpenInstance(Open);

 

         //

         // complete the IRP

         //

         Irp->IoStatus.Information = Information;

         Irp->IoStatus.Status = Status;

         IoCompleteRequest(Irp, IO_NO_INCREMENT);

 

 

         TRACE_EXIT();

 

         return Status;

}

 

对应该函数中的BIOCSETOID,通过  NdisRequest(

                    &Status,

                    Open->AdapterHandle,

                    &pRequest->Request

                    );

函数将请求发送给网卡;

VOID NdisRequest(

  PNDIS_STATUS Status,

  NDIS_HANDLE NdisBindingHandle,

  PNDIS_REQUEST NdisRequest

);

Parameters

Status

[in] Pointer to a caller-supplied variable that is set on return from this function. The underlying driver determines which NDIS_STATUS_XXX is returned.

NdisBindingHandle

[in] Handle returned by the NdisOpenAdapter function that identifies the target NIC or the virtual adapter of the next-lower driver to which the caller is bound.

NdisRequest

[in] Pointer to a buffered structure specifying the operation requested with a specified OID_XXX code for either a query or a set.

Return Values

The following table shows typical return values for this function.

 

这篇关于庖丁解牛---winpcap源码彻底解密系列的续集(7)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/599855

相关文章

python实现对数据公钥加密与私钥解密

《python实现对数据公钥加密与私钥解密》这篇文章主要为大家详细介绍了如何使用python实现对数据公钥加密与私钥解密,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录公钥私钥的生成使用公钥加密使用私钥解密公钥私钥的生成这一部分,使用python生成公钥与私钥,然后保存在两个文

如何在Mac上彻底删除Edge账户? 手动卸载Edge浏览器并清理残留文件技巧

《如何在Mac上彻底删除Edge账户?手动卸载Edge浏览器并清理残留文件技巧》Mac上的Edge账户里存了不少网站密码和个人信息,结果同事一不小心打开了,简直尴尬到爆炸,想要卸载edge浏览器并清... 如果你遇到 Microsoft Edge 浏览器运行迟缓、频繁崩溃或网页加载异常等问题,可以尝试多种方

一文彻底搞懂Java 中的 SPI 是什么

《一文彻底搞懂Java中的SPI是什么》:本文主要介绍Java中的SPI是什么,本篇文章将通过经典题目、实战解析和面试官视角,帮助你从容应对“SPI”相关问题,赢得技术面试的加分项,需要的朋... 目录一、面试主题概述二、高频面试题汇总三、重点题目详解✅ 面试题1:Java 的 SPI 是什么?如何实现一个

8种快速易用的Python Matplotlib数据可视化方法汇总(附源码)

《8种快速易用的PythonMatplotlib数据可视化方法汇总(附源码)》你是否曾经面对一堆复杂的数据,却不知道如何让它们变得直观易懂?别慌,Python的Matplotlib库是你数据可视化的... 目录引言1. 折线图(Line Plot)——趋势分析2. 柱状图(Bar Chart)——对比分析3

使用Java实现Navicat密码的加密与解密的代码解析

《使用Java实现Navicat密码的加密与解密的代码解析》:本文主要介绍使用Java实现Navicat密码的加密与解密,通过本文,我们了解了如何利用Java语言实现对Navicat保存的数据库密... 目录一、背景介绍二、环境准备三、代码解析四、核心代码展示五、总结在日常开发过程中,我们有时需要处理各种软

Android实现一键录屏功能(附源码)

《Android实现一键录屏功能(附源码)》在Android5.0及以上版本,系统提供了MediaProjectionAPI,允许应用在用户授权下录制屏幕内容并输出到视频文件,所以本文将基于此实现一个... 目录一、项目介绍二、相关技术与原理三、系统权限与用户授权四、项目架构与流程五、环境配置与依赖六、完整

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

如何将Python彻底卸载的三种方法

《如何将Python彻底卸载的三种方法》通常我们在一些软件的使用上有碰壁,第一反应就是卸载重装,所以有小伙伴就问我Python怎么卸载才能彻底卸载干净,今天这篇文章,小编就来教大家如何彻底卸载Pyth... 目录软件卸载①方法:②方法:③方法:清理相关文件夹软件卸载①方法:首先,在安装python时,下

Java中使用Hutool进行AES加密解密的方法举例

《Java中使用Hutool进行AES加密解密的方法举例》AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个,下面:本文主要介绍Java中使用Hutool进行AES加密解密的相关资料... 目录前言一、Hutool简介与引入1.1 Hutool简介1.2 引入Hutool二、AES加密解密基础