📄 packet.h
字号:
maintaining information about the IRPs to complete.
*/
typedef struct _PACKET_RESERVED {
LIST_ENTRY ListElement; ///< Used to handle lists of packets.
PIRP Irp; ///< Irp that performed the request
PMDL pMdl; ///< MDL mapping the buffer of the packet.
BOOLEAN FreeBufAfterWrite; ///< True if the memory buffer associated with the packet must be freed
///< after a call to NdisSend().
ULONG Cpu; ///< The CPU on which the packet was pulled out of the linked list of free packets
} PACKET_RESERVED, *PPACKET_RESERVED;
#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) ///< Macro to obtain a NDIS_PACKET from a PACKET_RESERVED
/*!
\brief Port device extension.
Structure containing some data relative to every adapter on which NPF is bound.
*/
typedef struct _DEVICE_EXTENSION {
NDIS_HANDLE NdisProtocolHandle; ///< NDIS handle of NPF.
NDIS_STRING AdapterName; ///< Name of the adapter.
PWSTR ExportString; ///< Name of the exported device, i.e. name that the applications will use
///< to open this adapter through WinPcap.
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
/*!
\brief Kernel buffer of each CPU.
Structure containing the kernel buffer (and other CPU related fields) used to capture packets.
*/
typedef struct __CPU_Private_Data
{
ULONG P; ///< Zero-based index of the producer in the buffer. It indicates the first free byte to be written.
ULONG C; ///< Zero-based index of the consumer in the buffer. It indicates the first free byte to be read.
ULONG Free; ///< Number of the free bytes in the buffer
PUCHAR Buffer; ///< Pointer to the kernel buffer used to capture packets.
ULONG Accepted; ///< Number of packet that current capture instance acepted, from its opening. A packet
///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the
///< ones that reach the application.
///< This number is related to the particular CPU this structure is referring to.
ULONG Received; ///< Number of packets received by current instance from its opening, i.e. number of
///< packet received by the network adapter since the beginning of the
///< capture/monitoring/dump session.
///< This number is related to the particular CPU this structure is referring to.
ULONG Dropped; ///< Number of packet that current instance had to drop, from its opening. A packet
///< is dropped if there is no more space to store it in the circular buffer that the
///< driver associates to current instance.
///< This number is related to the particular CPU this structure is referring to.
ULONG Processing; ///< Flag. If set to 1, it indicates that the tap is processing a packet on the CPU this structure is referring to.
PMDL TransferMdl1; ///< MDL used to map the portion of the buffer that will contain an incoming packet.
PMDL TransferMdl2; ///< Second MDL used to map the portion of the buffer that will contain an incoming packet.
ULONG NewP; ///< Used by NdisTransferData() (when we call NdisTransferData, p index must be updated only in the TransferDataComplete.
}
CpuPrivateData;
/*!
\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.
PIRP OpenCloseIrp; ///< Pointer used to store the open/close IRP requests and provide them to the
///< callbacks of NDIS.
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.
HANDLE ReadEventHandle; ///< Handle of the event on which the read calls on this instance must wait.
UNICODE_STRING ReadEventName; ///< Name of the event on which the read calls on this instance must wait.
///< The event is created with a name, so it can be used at user level to know when it
///< is possible to access the driver without being blocked. This fiels stores the name
///< that and is used by the BIOCGEVNAME IOCTL call.
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.
JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter.
///< See BPF_jitter() for details.
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
UINT 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.
NDIS_EVENT IOEvent; ///< Event used to synchronize I/O requests with the callback structure of NDIS.
NDIS_STATUS IOStatus; ///< Maintains the status of and OID request call, that will be passed to the application.
BOOLEAN Bound; ///< Specifies if NPF is still bound to the adapter used by this instance. Bound can be
///< FALSE if a Plug and Play adapter has been removed or disabled by the user.
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 mem_ex buffer
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 SkipProcessing; ///< Flag. When set to 1, the tap discards each packet. It is set to 1 by the IOCTLs that modify
///< some "sensible" fields of the Open structure (e.g. they reallocate the pool of kernel buffers,
///< or change the filter program
}
OPEN_INSTANCE, *POPEN_INSTANCE;
/*!
\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.
};
#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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -