庖丁解牛---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

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

Java 后端接口入参 - 联合前端VUE 使用AES完成入参出参加密解密

加密效果: 解密后的数据就是正常数据: 后端:使用的是spring-cloud框架,在gateway模块进行操作 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>30.0-jre</version></dependency> 编写一个AES加密