📄 packet.h
字号:
/*!
\brief Contains the state of a running instance of the NPF driver.
This is the most important structure of NPF: it is used by almost all the functions of the driver. An
_OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
to the driver.
*/
typedef struct _OPEN_INSTANCE
{
PDEVICE_EXTENSION DeviceExtension; ///< Pointer to the _DEVICE_EXTENSION structure of the device on which
///< the instance is bound.
NDIS_HANDLE AdapterHandle; ///< NDIS idetifier of the adapter used by this instance.
UINT Medium; ///< Type of physical medium the underlying NDIS driver uses. See the
///< documentation of NdisOpenAdapter in the MS DDK for details.
NDIS_HANDLE PacketPool; ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
KSPIN_LOCK RequestSpinLock; ///< SpinLock used to synchronize the OID requests.
LIST_ENTRY RequestList; ///< List of pending OID requests.
LIST_ENTRY ResetIrpList; ///< List of pending adapter reset requests.
INTERNAL_REQUEST Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request.
PMDL BufferMdl; ///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory.
PKEVENT ReadEvent; ///< Pointer to the event on which the read calls on this instance must wait.
PUCHAR bpfprogram; ///< Pointer to the filtering pseudo-code associated with current instance of the driver.
///< This code is used only in particular situations (for example when the packet received
///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
///< the filtering routine created by the JIT compiler and pointed by the next field
///< is used. See \ref NPF for details on the filtering process.
#ifdef __NPF_x86__
JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter.
///< See BPF_jitter() for details.
#endif
UINT MinToCopy; ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
///< BIOCSMINTOCOPY IOCTL.
LARGE_INTEGER TimeOut; ///< Timeout after which a read is released, also if the amount of data in the buffer is
///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
int mode; ///< Working mode of the driver. See PacketSetMode() for details.
LARGE_INTEGER Nbytes; ///< Amount of bytes accepted by the filter when this instance is in statistical mode.
LARGE_INTEGER Npackets; ///< Number of packets accepted by the filter when this instance is in statistical mode.
NDIS_SPIN_LOCK CountersLock; ///< SpinLock that protects the statistical mode counters.
UINT Nwrites; ///< Number of times a single write must be physically repeated. See \ref NPF for an
///< explanation
ULONG Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated.
NDIS_EVENT WriteEvent; ///< Event used to synchronize the multiple write process.
BOOLEAN WriteInProgress; ///< True if a write is currently in progress. NPF currently allows a single wite on
///< the same open instance.
NDIS_SPIN_LOCK WriteLock; ///< SpinLock that protects the WriteInProgress variable.
NDIS_EVENT NdisRequestEvent; ///< Event used to synchronize I/O requests with the callback structure of NDIS.
BOOLEAN SkipSentPackets; ///< True if this instance should not capture back the packets that it transmits.
NDIS_STATUS IOStatus; ///< Maintains the status of and OID request call, that will be passed to the application.
HANDLE DumpFileHandle; ///< Handle of the file used in dump mode.
PFILE_OBJECT DumpFileObject; ///< Pointer to the object of the file used in dump mode.
PKTHREAD DumpThreadObject; ///< Pointer to the object of the thread used in dump mode.
HANDLE DumpThreadHandle; ///< Handle of the thread created by dump mode to asynchronously move the buffer to disk.
NDIS_EVENT DumpEvent; ///< Event used to synchronize the dump thread with the tap when the instance is in dump mode.
LARGE_INTEGER DumpOffset; ///< Current offset in the dump file.
UNICODE_STRING DumpFileName; ///< String containing the name of the dump file.
UINT MaxDumpBytes; ///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it
///< will be closed. A value of 0 means unlimited size.
UINT MaxDumpPacks; ///< Maximum number of packets that will be saved in the dump file. If this number of
///< packets is reached the dump will be closed. A value of 0 means unlimited number of
///< packets.
BOOLEAN DumpLimitReached; ///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is
///< reached.
MEM_TYPE mem_ex; ///< Memory used by the TME virtual co-processor
TME_CORE tme; ///< Data structure containing the virtualization of the TME co-processor
NDIS_SPIN_LOCK MachineLock; ///< SpinLock that protects the BPF filter and the TME engine, if in use.
UINT MaxFrameSize; ///< Maximum frame size that the underlying MAC acceptes. Used to perform a check on the
///< size of the frames sent with NPF_Write() or NPF_BufferedWrite().
CpuPrivateData CpuData[32]; ///< Pool of kernel buffer structures, one for each CPU.
ULONG ReaderSN; ///< Sequence number of the next packet to be read from the pool of kernel buffers.
ULONG WriterSN; ///< Sequence number of the next packet to be written in the pool of kernel buffers.
///< These two sequence numbers are unique for each capture instance.
ULONG Size; ///< Size of each kernel buffer contained in the CpuData field.
ULONG AdapterHandleUsageCounter;
NDIS_SPIN_LOCK AdapterHandleLock;
ULONG AdapterBindingStatus; ///< Specifies if NPF is still bound to the adapter used by this instance, it's unbinding or it's not bound.
NDIS_EVENT NdisOpenCloseCompleteEvent;
NDIS_EVENT NdisWriteCompleteEvent; ///< Event that is signalled when all the packets have been successfully sent by NdisSend (and corresponfing sendComplete has been called)
NTSTATUS OpenCloseStatus;
ULONG TransmitPendingPackets; ///< Specifies the number of packets that are pending to be transmitted, i.e. have been submitted to NdisSendXXX but the SendComplete has not been called yet.
}
OPEN_INSTANCE, *POPEN_INSTANCE;
enum ADAPTER_BINDING_STATUS
{
ADAPTER_UNBOUND,
ADAPTER_BOUND,
ADAPTER_UNBINDING,
};
/*!
\brief Structure prepended to each packet in the kernel buffer pool.
Each packet in one of the kernel buffers is prepended by this header. It encapsulates the bpf_header,
which will be passed to user level programs, as well as the sequence number of the packet, set by the producer (the tap function),
and used by the consumer (the read function) to "reorder" the packets contained in the various kernel buffers.
*/
struct PacketHeader
{
ULONG SN; ///< Sequence number of the packet.
struct bpf_hdr header; ///< bpf header, created by the tap, and copied unmodified to user level programs.
};
extern ULONG NCpu;
#define TRANSMIT_PACKETS 256 ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.
/// Macro used in the I/O routines to return the control to user-mode with a success status.
#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\
Irp->IoStatus.Status = STATUS_SUCCESS;\
IoCompleteRequest(Irp, IO_NO_INCREMENT);\
return STATUS_SUCCESS;\
/// Macro used in the I/O routines to return the control to user-mode with a failure status.
#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\
IoCompleteRequest(Irp, IO_NO_INCREMENT);\
return STATUS_UNSUCCESSFUL;\
/**
* @}
*/
/***************************/
/* Prototypes */
/***************************/
/** @defgroup NPF_code NPF functions
* @{
*/
/*!
\brief The initialization routine of the driver.
\param DriverObject The driver object of NPF created by the system.
\param RegistryPath The registry path containing the keys related to the driver.
\return A string containing a list of network adapters.
DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called
by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver,
performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O
callbacks, creates the devices, defines NPF as a protocol inside NDIS.
*/
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
/*!
\brief Returns the list of the MACs available on the system.
\return A string containing a list of network adapters.
The list of adapters is retrieved from the
SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key.
NPF tries to create its bindings from this list. In this way it is possible to be loaded
and unloaded dynamically without passing from the control panel.
*/
PWCHAR getAdaptersList(VOID);
/*!
\brief Returns the MACs that bind to TCP/IP.
\return Pointer to the registry key containing the list of adapters on which TCP/IP is bound.
If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function.
*/
PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID);
/*!
\brief Creates a device for a given MAC.
\param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF.
\param amacNameP The name of the network interface that the device will point.
\param aProtoHandle NDIS protocol handle of NPF.
\return If the function succeeds, the return value is nonzero.
NPF creates a device for every valid network adapter. The new device points to the NPF driver, but contains
information about the original device. In this way, when the user opens the new device, NPF will be able to
determine the correct adapter to use.
*/
BOOLEAN createDevice(
IN OUT PDRIVER_OBJECT adriverObjectP,
IN PUNICODE_STRING amacNameP,
NDIS_HANDLE aProtoHandle);
/*!
\brief Opens a new instance of the driver.
\param DeviceObject Pointer to the device object utilized by the user.
\param Irp Pointer to the IRP containing the user request.
\return The status of the operation. See ntstatus.h in the DDK.
This function is called by the OS when a new instance of the driver is opened, i.e. when a user application
performs a CreateFile on a device created by NPF. NPF_Open allocates and initializes variables, objects
and buffers needed by the new instance, fills the OPEN_INSTANCE structure associated with it and opens the
adapter with a call to NdisOpenAdapter.
*/
NTSTATUS
NPF_Open(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
/*!
\brief Ends the opening of an adapter.
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
\param Status Status of the opening operation performed by NDIS.
\param OpenErrorStatus not used by NPF.
Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC
driver has finished an open operation that was previously started by NPF_Open().
*/
VOID
NPF_OpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
);
/*!
\brief Closes an instance of the driver.
\param DeviceObject Pointer to the device object utilized by the user.
\param Irp Pointer to the IRP containing the user request.
\return The status of the operation. See ntstatus.h in the DDK.
This function is called when a running instance of the driver is closed by the user with a CloseHandle().
It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the
instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter.
*/
NTSTATUS
NPF_Cleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
NPF_Close(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
/*!
\brief Ends the closing of an adapter.
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
\param Status Status of the close operation performed by NDIS.
Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC
driver has finished a close operation that was previously started by NPF_Close().
*/
VOID
NPF_CloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
);
/*!
\brief Callback invoked by NDIS when a packet arrives from the network.
\param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies
the NPF instance to which the packets are destined.
\param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request.
This value must be used when the packet is transferred from the NIC driver with NdisTransferData().
\param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet.
\param HeaderBufferSize Size in bytes of the header.
\param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's
data <b>available to NPF</b>. This value does not necessarily coincide with the actual size of the packet,
since only a portion can be available at this time. The remaining portion can be obtained with the
NdisTransferData() NDIS function.
\param LookaheadBufferSize Size in bytes of the lookahead buffer.
\param PacketSize Total size of the incoming packet, excluded the header.
\return The status of the operation. See ntstatus.h in the DDK.
NPF_tap() is called by the underlying NIC for every incoming packet. It is the most important and one of
the most complex functions of NPF: it executes the filter, runs the statistical engine (if the instance is in
statistical mode), gathers the timestamp, moves the packet in the buffer. NPF_tap() is the only function,
along with the filtering ones, that is executed for every incoming packet, therefore it is carefully
optimized.
*/
NDIS_STATUS
NPF_tap(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize
);
/*!
\brief Ends the transfer of a packet.
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
\param Packet Pointer to the NDIS_PACKET structure that received the packet data.
\param Status Status of the transfer operation.
\param BytesTransferred Amount of bytes transferred.
Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC
driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer.
*/
VOID
NPF_TransferDataComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status,
IN UINT BytesTransferred
);
/*!
\brief Callback function that signals the end of a packet reception.
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
does nothing in NPF
*/
VOID
NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext);
/*!
\brief Handles the IOCTL calls.
\param DeviceObject Pointer to the device object utilized by the user.
\param Irp Pointer to the IRP containing the user request.
\return The status of the operation. See ntstatus.h in the DDK.
Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands
using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF.
The following commands are recognized:
- #BIOCSETBUFFERSIZE
- #BIOCSETF
- #BIOCGSTATS
- #BIOCSRTIMEOUT
- #BIOCSMODE
- #BIOCSWRITEREP
- #BIOCSMINTOCOPY
- #BIOCSETOID
- #BIOCQUERYOID
- #BIOCSETDUMPFILENAME
- #BIOCGEVNAME
- #BIOCSENDPACKETSSYNC
- #BIOCSENDPACKETSNOSYNC
*/
NTSTATUS
NPF_IoControl(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -