The Npcap API
The Npcap Application Programming Interface (API) consists of the
libpcap API and a few non-portable extensions: pcap_setbuff,
pcap_setuserbuffer,
pcap_setmintocopy,
pcap_getevent,
pcap_setmode,
pcap_oid_get_request and pcap_oid_set_request,
functions for batch-sending packets with pcap_send_queue,
and pcap_stats_ex.
The Npcap API is exported by wpcap.dll and is the
Windows port of libpcap.
The API and functions are described in
the pcap(1) man page.
This port varies from the standard Unix libpcap API in just a few ways.
First, the pcap_get_selectable_fd() and
pcap_get_required_select_timeout()
functions are not defined or exported. Second, as described in
the section called “Extensions to libpcap for Windows”, Npcap extends the libpcap API with
a set of non-portable functions. Lastly, Npcap includes functions from the
remote capture API of libpcap, which is described in
the section called “The libpcap remote capture API”.
Extensions to libpcap for Windows
There are a few extensions to libpcap that exist only on Windows. Software that uses these extensions will not be portable to non-Windows systems. The following is a brief list of these extensions and their purpose.
-
pcap_setbuff Sets the size of the kernel buffer associated with an adapter.
int pcap_setbuff(pcap_t *p, int dim);dimspecifies the size of the buffer in bytes. The return value is 0 when the call succeeds, -1 otherwise. If an old buffer was already created with a previous call topcap_setbuff(), it is deleted and its content is discarded. pcap_open_live() creates a 1 MByte buffer by default.Portability note: libpcap provides the pcap_set_buffer_size() function for setting the kernel buffer size. This removes the need to use the non-portable
pcap_setbuff()for this purpose.-
pcap_setmode Sets the working mode of the interface.
int pcap_setmode(pcap_t *p, int mode);The
modeparameter is defined as a bitwise-OR of the constants defined below. These are bit flags and may be combined using bitwise-OR to enable multiple behaviors.MODE_CAPTandMODE_STATshare the same bit position:MODE_CAPTis defined as 0 (LSB clear) andMODE_STATas 1 (LSB set). As a result,MODE_CAPTis mutually exclusive withMODE_STATand cannot be explicitly combined with it.Valid values for mode are listed below. WinPcap also defined
MODE_MONandMODE_DUMP, but these are not supported by Npcap.-
MODE_CAPT Default packet capture mode.
-
MODE_STAT Statistical mode. See the section called “Gathering Statistics on the network traffic” for details.
-
MODE_SENDTORX Causes injected packets to be sent on the receive path as though they were received by the network adapter. This is the same behavior as the SendToRxAdapters Registry value, but affects only this handle.
![[Note]](images/note.png)
Note This mode was added in Npcap 1.83
-
MODE_SENDTORX_CLEAR Forces this handle to use the default behavior (sending injected packets on the transmit path), canceling any system-wide Npcap configuration by the SendToRxAdapters Registry value.
![[Note]](images/note.png)
Note This mode was added in Npcap 1.83
-
-
pcap_setmintocopy Sets the minumum amount of data received by the kernel in a single call.
int pcap_setmintocopy(pcap_t *p, int size);This function changes the minimum amount of data in the kernel buffer that causes a read from the application to return (unless the timeout expires). If the value of
sizeis large, the kernel is forced to wait the arrival of several packets before copying the data to the user. This guarantees a low number of system calls, i.e. low processor usage, and is a good setting for applications like packet-sniffers and protocol analyzers. Vice versa, in presence of a small value for this variable, the kernel will copy the packets as soon as the application is ready to receive them. This is useful for real time applications that need the best responsiveness from the kernel. pcap_open_live() sets a defaultsizevalue of 16000 bytes.Portability note: libpcap provides the pcap_set_immediate_mode() function for applications that need to receive packets as soon as they arrive. This removes the need to use the non-portable
pcap_setmintocopy()for this purpose.-
pcap_getevent Returns the handle of the event associated with the interface.
HANDLE pcap_getevent(pcap_t *p);This event can be passed to functions like
WaitForSingleObject()orWaitForMultipleObjects()to wait until the driver's buffer contains some data without performing a read.Portability note: This function is the Windows alternative to pcap_get_selectable_fd(), which is only available on UNIX-like systems.
-
pcap_oid_get_requestandpcap_oid_set_request Send an OID request to the underlying NDIS drivers
int pcap_oid_get_request(pcap_t *, bpf_u_int32, void *, size_t *);int pcap_oid_set_request(pcap_t *, bpf_u_int32, const void *, size_t *);-
Queuing sent packets with
pcap_send_queue Npcap has the ability to queue multiple raw packets for transmission on the network in a single call. This is more efficient than issuing a series of
pcap_sendpacket(), because the packets are buffered in the kernel driver, so the number of context switches is reduced.pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);void pcap_sendqueue_destroy(pcap_send_queue* queue);Allocate a send queue as a buffer of
memsizebytes. Thepcap_send_queueallocated can be freed withpcap_sendqueue_destroy().int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);pcap_sendqueue_queue()adds a packet at the end of the send queue pointed by thequeueparameter.pkt_headerpoints to apcap_pkthdrstructure with the timestamp and the length of the packet,pkt_datapoints to a buffer with the data of the packet.The
pcap_pkthdrstructure is the same used by Npcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward. 'Raw packet' means that the sending application will have to include the protocol headers, since every packet is sent to the network 'as is'. The CRC of the packets needs not to be calculated, because it will be transparently added by the network interface.u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);This function transmits the content of a queue to the wire.
pis a pointer to the adapter on which the packets will be sent,queuepoints to apcap_send_queuestructure containing the packets to send),syncdetermines if the send operation must be synchronized: if it is non-zero, the packets are sent respecting the timestamps, otherwise they are sent as fast as possible.The return value is the amount of bytes actually sent. If it is smaller than the
sizeparameter, an error occurred during the send. The error can be caused by a driver/adapter problem or by an inconsistent/bogus send queue.Performance note: When
syncis set toTRUE, the packets are synchronized in the kernel with a high precision timestamp. This requires a non-negligible amount of CPU, but allows normally to send the packets with a precision of some microseconds (depending on the accuracy of the performance counter of the machine). Such a precision cannot be reached sending the packets withpcap_sendpacket().-
pcap_stats_ex struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size);pcap_stats_ex()extends thepcap_stats()allowing to return more statistical parameters than the old call. One of the advantages of this new call is that thepcap_statstructure is not allocated by the user; instead, it is returned back by the system. This allow to extend thepcap_statstructure without affecting backward compatibility on older applications. These will simply check at the values of the members at the beginning of the structure, while only newest applications are able to read new statistical values, which are appended in tail.To be sure not to read a piece of memory which has not been allocated by the system, the variable
pcap_stat_sizewill return back the size of the structurepcap_statallocated by the system.p: pointer to thepcap_tcurrently in use.pcap_stat_size: pointer to an integer that will contain (when the function returns back) the size of the structurepcap_statas it has been allocated by the system.The function returns a pointer to a pcap_stat structure, that will contain the statistics related to the current device. The return value is
NULLin case of errors, and the error text can be obtained withpcap_perror()orpcap_geterr().-
pcap_setuserbuffer Sets the size of the buffer that accepts packets from the kernel driver.
int pcap_setuserbuffer(pcap_t *p, int size);The size of the packet buffer is a parameter that can sensibly influence the performance of the capture process, since this buffer will contain the packets received from the the Npcap driver. The driver is able to return several packets using a single read call, and the number of packets transferable to the application in a call is limited only by the size of this buffer. Therefore setting a larger buffer siz can noticeably decrease the number of system calls, reducing the impact of the capture process on the processor.
The libpcap remote capture API
WinPcap introduced several additional functions to the libpcap API in order to support remote capture. While the upstream libpcap project has absorbed these functions, they have not yet published documentation on them. Here is a brief overview.
-
pcap_open Opens a remote or local capture handle.
pcap_t* pcap_open(const char * source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf);This routine can open a savefile, a local device, or a device on a remote machine running an RPCAP server.
sourceZero-terminated string containing the source name to open. The source name must be in one of the following formats:
file://path/to/file.pcaprpcap://devicename(or the equivalent,devicename)rpcap://host/devicenamerpcap://host:port/devicename
Adapter names returned by
pcap_findalldevs_ex()are already in this format. For convenience, compatible source strings can be built with the helper function,int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf), wheretypeis one ofPCAP_SRC_FILE,PCAP_SRC_IFLOCAL, orPCAP_SRC_IFREMOTE, andsourceis a user-allocated buffer of at leastPCAP_BUF_SIZEbytes.snaplenSee the documentation for pcap_open_live().
flagsKeeps several flags that can be needed for capturing packets. The allowed flags are defined in the pcap_open() flags .
read_timeout>See the documentation for pcap_open_live().
authA pointer to a 'struct pcap_rmtauth' that keeps the information required to authenticate the user on a remote machine. In case this is not a remote capture, this pointer can be set to NULL.
errbufSee the documentation for pcap_open_live().
Portability notes: For opening a savefile, the pcap_open_offline routines can be used, and will work just as well; code using them will work on more platforms than code using
pcap_open()to open savefiles.For opening a local device, pcap_open_live() can be used; it supports most of the capabilities than
pcap_open()supports, and code using it will work on more platforms than code usingpcap_open(). pcap_create() and pcap_activate() can also be used; they support all capabilities thatpcap_open()supports, except for the Windows-onlyPCAP_OPENFLAG_NOCAPTURE_LOCAL, and they support additional capabilities.For opening a remote capture,
pcap_open()is currently the only API available.-
pcap_findalldevs_ex Lists local and remote capture sources.
int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);sourceZero-terminated string containing the source name to list. The source name must be in one of the following formats:
file://path/to/directory- lists capture files in a directoryrpcap://- lists local adaptersrpcap://host[:port]- lists remote adapters
authSee
pcap_open().alldevsSee pcap_findalldevs().
errbufSee pcap_findalldevs().
As with
pcap_findalldevs(), the buffer returned inalldevsmust be freed using pcap_freealldevs().
Implementation-specific API details
Some libpcap functions and features can vary from platform to platform. Here are some specific clarifications for those cases.
- Statistics reported by
pcap_stats() In Npcap, the members of
struct pcap_statare:ps_recvThe number of packets processed by this handle, regardless of whether they passed the packet filter.
ps_dropThe number of packets dropped due to resource limits or a full buffer
ps_ifdropNot used. This is always set to 0.
ps_captFor
pcap_stats(), this is not used. Forpcap_stats_ex(), this is the number of packets that passed the packet filter AND were queued for capture (i.e. not dropped due to limited buffer space).ps_sentNot used.
ps_netdropNot used.
- Timestamp types
Npcap supports the following timestamp types for
pcap_set_tstamp_type():PCAP_TSTAMP_HOSTDefault timestamp type, usually
TIMESTAMP_MODE_SINGLE_SYNCHRONIZATION. Registry settings may change this default for new handles.PCAP_TSTAMP_HOST_HIPREC_UNSYNCEDMaps to
TIMESTAMP_MODE_SINGLE_SYNCHRONIZATION, a monotonic timestamp based on the system performance counter (KeQueryPerformanceCounter()). This may drift from system time, but will never move backward.PCAP_TSTAMP_HOST_LOWPRECMaps to
TIMESTAMP_MODE_QUERYSYSTEMTIME. Timestamps are synchronized to the system clock and obtained by callingKeQuerySystemTime(), which is accurate to within one system clock tick (roughly ten milliseconds). If the system time moves backwards due to NTP or other time change, the timestamps will also go backwards.PCAP_TSTAMP_HOST_HIPRECMaps to
TIMESTAMP_MODE_QUERYSYSTEMTIME_PRECISE. Timestamps are synchronized to the system clock and obtained by callingKeQuerySystemTimePrecise(), which is accurate to within a microsecond.Note that Windows 7 does not have the
KeQuerySystemTimePrecise()function, soPCAP_TSTAMP_HOST_HIPRECis identical toPCAP_TSTAMP_HOST_LOWPRECon that system.
- Timestamp precision
Npcap 1.86 and later support requesting timestamps in nanosecond precision using
pcap_set_tstamp_precision(). The timestamps are still subject to the 100-nanosecond resolution of the Windows system clock.
