📄 wanpacket.cpp
字号:
pWanAdapter->Buffer = NewBuffer;
pWanAdapter->Size = BufferSize;
pWanAdapter->C = 0;
pWanAdapter->P = 0;
pWanAdapter->Free = BufferSize;
LeaveCriticalSection(&pWanAdapter->CriticalSection);
return TRUE;
}
/*!
\brief Read data (packets or statistics) from this wan (dialup, vpn...) instance.
\param pWanAdapter Pointer to a WAN_ADAPTER structure.
\param Buffer Buffer that will receive the data.
\param BufferSize Size of receiving buffer.
\return It returns the number of written bytes in the buffer.
For more information, see the documentation of PacketReceivePacket
*/
DWORD WanPacketReceivePacket(PWAN_ADAPTER pWanAdapter, PUCHAR Buffer, DWORD BufferSize)
{
DWORD ReadBytes = 0;
//first of all, we wait for either the ReadTimeout to expire, or enough data
//in the buffer (i.e. hReadEvent gets set).
WaitForSingleObject(pWanAdapter->hReadEvent, pWanAdapter->ReadTimeout);
//we have to prevent other entities from modifying the pWanAdapter structure
EnterCriticalSection(&pWanAdapter->CriticalSection);
if ( pWanAdapter->Mode == PACKET_MODE_CAPT )
{ //capture mode, we have an ad-hoc fcn
ReadBytes = WanPacketRemovePacketsFromRingBuffer(pWanAdapter, Buffer, BufferSize);
}
if ( pWanAdapter->Mode == PACKET_MODE_STAT )
{
if ( BufferSize < sizeof(LONGLONG) * 2 + sizeof(struct bpf_hdr))
ReadBytes = 0; //not enough space in the dest buffer
else
{
//insert tthe bpf header
((struct bpf_hdr*)Buffer)->bh_caplen = 2*sizeof(LONGLONG);
((struct bpf_hdr*)Buffer)->bh_datalen = 2*sizeof(LONGLONG);
((struct bpf_hdr*)Buffer)->bh_hdrlen = sizeof(struct bpf_hdr);
((struct bpf_hdr*)Buffer)->bh_tstamp = WanPacketGetCurrentTime();
//copy the counters
((LONGLONG*)(Buffer + sizeof(struct bpf_hdr)))[0] = pWanAdapter->Npackets.QuadPart;
((LONGLONG*)(Buffer + sizeof(struct bpf_hdr)))[1] = pWanAdapter->Nbytes.QuadPart;
ReadBytes = sizeof(struct bpf_hdr) + 2 + sizeof(LONGLONG);
//reset the counters
pWanAdapter->Nbytes.QuadPart = 0;
pWanAdapter->Npackets.QuadPart = 0;
}
}
if ( pWanAdapter->Mode == PACKET_MODE_MON )
{
PTME_DATA pTmeData;
DWORD ByteCopy;
struct bpf_hdr *pHeader;
if (
!IS_VALIDATED(pWanAdapter->Tme.validated_blocks, pWanAdapter->Tme.active_read)
|| BufferSize < sizeof(struct bpf_hdr)
)
{ //the TME is either not active, or no tme block has been set to be used for passing data to the user
ReadBytes = 0;
}
else
{
//insert the bpf header
pHeader = (struct bpf_hdr*)Buffer;
pHeader->bh_tstamp = WanPacketGetCurrentTime();
pHeader->bh_hdrlen = sizeof(struct bpf_hdr);
pTmeData = &pWanAdapter->Tme.block_data[pWanAdapter->Tme.active_read];
if ( pTmeData->last_read.tv_sec != 0 )
pTmeData->last_read = pHeader->bh_tstamp;
//check the amount of data that must be copied
ByteCopy = pTmeData->block_size * pTmeData->filled_blocks;
if ( BufferSize - sizeof(struct bpf_hdr) < ByteCopy )
ByteCopy = BufferSize - sizeof(struct bpf_hdr); //we copy only the data that fit in the buffer
else
ByteCopy = pTmeData->filled_blocks * pTmeData->block_size; //we copy all the data
//actual copy of data
RtlCopyMemory(Buffer + sizeof(struct bpf_hdr), pTmeData->shared_memory_base_address, ByteCopy);
//fix the bpf header
pHeader->bh_caplen = ByteCopy;
pHeader->bh_datalen = pHeader->bh_caplen;
ReadBytes = ByteCopy + sizeof(struct bpf_hdr);
}
}
//done with the pWanAdapter data
LeaveCriticalSection(&pWanAdapter->CriticalSection);
return ReadBytes;
}
/*!
\brief Defines the minimum amount of data that will be received in a read.
\param pWanAdapter Pointer to a WAN_ADAPTER structure
\param MinToCopy The minimum amount of data in the ring buffer that will cause the instance to release a read on this adapter.
\return If the function succeeds, the return value is TRUE.
For more information, see the documentation of PacketSetMinToCopy
*/
BOOLEAN WanPacketSetMinToCopy(PWAN_ADAPTER pWanAdapter, DWORD MinToCopy)
{
EnterCriticalSection( &pWanAdapter->CriticalSection );
pWanAdapter->MinToCopy = MinToCopy;
LeaveCriticalSection( &pWanAdapter->CriticalSection );
return TRUE;
}
/*!
\brief Returns statistic values about the current capture session.
\param pWanAdapter Pointer to a WAN_ADAPTER structure.
\param s Pointer to a user provided bpf_stat structure that will be filled by the function.
\return If the function succeeds, the return value is TRUE.
For more information, see the documentation of PacketGetStats and PacketGetStatsEx
*/
BOOLEAN WanPacketGetStats(PWAN_ADAPTER pWanAdapter, struct bpf_stat *s)
{
EnterCriticalSection (&pWanAdapter->CriticalSection);
s->bs_drop = pWanAdapter->Dropped;
s->bs_recv = pWanAdapter->Received;
s->bs_capt = pWanAdapter->Accepted;
s->ps_ifdrop = 0;
LeaveCriticalSection (&pWanAdapter->CriticalSection);
return TRUE;
}
/*!
\brief Sets the timeout after which a read on an wan adapter returns.
\param pWanAdapter Pointer to a WAN_ADAPTER structure.
\param ReadTimeout indicates the timeout, in milliseconds, after which a call to WanPacketReceivePacket() on
the adapter pointed by pWanAdapter will be released, even if no packets have been captured by NetMon IRTC.
Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives.
A timeout of -1 causes PacketReceivePacket() to always return immediately.
\return If the function succeeds, the return value is TRUE.
\note This function works also if the adapter is working in statistics mode, and can be used to set the
time interval between two statistic reports.
*/
BOOLEAN WanPacketSetReadTimeout(PWAN_ADAPTER pWanAdapter, DWORD ReadTimeout)
{
if (ReadTimeout == 0)
ReadTimeout = INFINITE;
else
if (ReadTimeout == -1)
ReadTimeout = 0;
EnterCriticalSection( &pWanAdapter->CriticalSection );
pWanAdapter->ReadTimeout = ReadTimeout;
LeaveCriticalSection( &pWanAdapter->CriticalSection );
return TRUE;
}
/*!
\brief Returns the notification event associated with the read calls on the wan adapter.
\param pWanAdapter Pointer to a WAN_ADAPTER structure.
\return The handle of the event that the the IRTC receive callback signals when some data is available in the ring buffer.
For more information, see the documentation of PacketGetReadEvent
*/
HANDLE WanPacketGetReadEvent(PWAN_ADAPTER pWanAdapter)
{
return pWanAdapter->hReadEvent;
}
/*!
\brief Moves the packets from the ring buffer to a given buffer.
\param pWanAdapter Pointer to WAN_ADAPTER structure associated with this instance.
\param Buffer Pointer to the destination, user allocated, buffer.
\param BuffSize Size of the buffer.
\return It returns the number of bytes correctly written to the destination buffer
*/
DWORD WanPacketRemovePacketsFromRingBuffer(PWAN_ADAPTER pWanAdapter, PUCHAR Buffer, DWORD BuffSize)
{
DWORD Copied;
struct bpf_hdr *Header;
Copied = 0;
DWORD ToCopy;
DWORD Increment;
ResetEvent(pWanAdapter->hReadEvent);
while (BuffSize > Copied)
{
if ( pWanAdapter->Free < pWanAdapter->Size )
{ //there are some packets in the selected (aka LocalData) buffer
Header = (struct bpf_hdr*)(pWanAdapter->Buffer + pWanAdapter->C);
if (Header->bh_caplen + sizeof (struct bpf_hdr) > BuffSize - Copied)
{ //if the packet does not fit into the user buffer, we've ended copying packets
return Copied;
}
*((struct bpf_hdr*)(Buffer + Copied)) = *Header;
Copied += sizeof(struct bpf_hdr);
pWanAdapter->C += sizeof(struct bpf_hdr);
if ( pWanAdapter->C == pWanAdapter->Size )
pWanAdapter->C = 0;
if ( pWanAdapter->Size - pWanAdapter->C < (DWORD)Header->bh_caplen )
{
//the packet is fragmented in the buffer (i.e. it skips the buffer boundary)
ToCopy = pWanAdapter->Size - pWanAdapter->C;
CopyMemory(Buffer + Copied,pWanAdapter->Buffer + pWanAdapter->C, ToCopy);
CopyMemory(Buffer + Copied + ToCopy, pWanAdapter->Buffer + 0, Header->bh_caplen - ToCopy);
pWanAdapter->C = Header->bh_caplen - ToCopy;
}
else
{
//the packet is not fragmented
CopyMemory(Buffer + Copied ,pWanAdapter->Buffer + pWanAdapter->C ,Header->bh_caplen);
pWanAdapter->C += Header->bh_caplen;
// if (c==size) inutile, contemplato nell "header atomico"
// c=0;
}
Copied += ALIGN_TO_WORD(Header->bh_caplen);
Increment = Header->bh_caplen + sizeof(struct bpf_hdr);
if ( pWanAdapter->Size - pWanAdapter->C < sizeof(struct bpf_hdr) )
{ //the next packet would be saved at the end of the buffer, but the NewHeader struct would be fragmented
//so the producer (--> the consumer) skips to the beginning of the buffer
Increment += pWanAdapter->Size - pWanAdapter->C;
pWanAdapter->C = 0;
}
pWanAdapter->Free += Increment;
}
else
return Copied;
}
return Copied;
}
/*!
\brief Adds a packet to the ring buffer.
\param pWanAdapter Pointer to WAN_ADAPTER structure associated with this instance.
\param lpFrameDesc Pointer to a packet as received by the IRTC receiver callback.
\param SnapToCopy Number of bytes to be copied from the packet to the ring buffer.
\param PacketTime Timestamp of the packet.
\return It returns TRUE if the copy was successful, FALSE if the packet did not fit in the ring buffer.
*/
BOOLEAN WanPacketAddPacketToRingBuffer(PWAN_ADAPTER pWanAdapter, LPFRAME_DESCRIPTOR lpFrameDesc, DWORD SnapToCopy, struct timeval PacketTime)
{
struct bpf_hdr *Header;
DWORD ToCopy;
DWORD increment;
if (SnapToCopy + sizeof(struct bpf_hdr) > pWanAdapter->Free)
return FALSE;
Header = (struct bpf_hdr*)(pWanAdapter->Buffer + pWanAdapter->P);
// We need to change reference from January, 1st 1601 to January, 1st 1970 = 11644473600 seconds if I'm right!!
Header->bh_tstamp = PacketTime;
if (SnapToCopy > lpFrameDesc->FrameLength)
SnapToCopy = lpFrameDesc->FrameLength;
Header->bh_caplen = SnapToCopy;
Header->bh_datalen = lpFrameDesc->FrameLength;
Header->bh_hdrlen = sizeof(struct bpf_hdr);
pWanAdapter->P += sizeof(struct bpf_hdr);
if ( pWanAdapter->P == pWanAdapter->Size )
pWanAdapter->P = 0;
if ( pWanAdapter->Size - pWanAdapter->P < SnapToCopy )
{
//the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
//two copies!!
ToCopy = pWanAdapter->Size - pWanAdapter->P;
CopyMemory(pWanAdapter->Buffer + pWanAdapter->P, lpFrameDesc->FramePointer, ToCopy);
CopyMemory(pWanAdapter->Buffer + 0 , (PUCHAR)lpFrameDesc->FramePointer + ToCopy, SnapToCopy - ToCopy);
pWanAdapter->P = SnapToCopy - ToCopy;
}
else
{
//the packet does not need to be fragmented in the buffer (aka, it doesn't skip the buffer boundary)
// ;-)))))) only ONE copy
CopyMemory(pWanAdapter->Buffer + pWanAdapter->P, lpFrameDesc->FramePointer, SnapToCopy);
pWanAdapter->P += SnapToCopy;
}
increment = SnapToCopy + sizeof(struct bpf_hdr);
if ( pWanAdapter->Size - pWanAdapter->P < sizeof(struct bpf_hdr) ) //we check that the available, AND contiguous, space in the buffer will fit
{ //the bpf_hdr structure, at least, otherwise we skip the producer
increment += pWanAdapter->Size - pWanAdapter->P; //at the beginning of the buffer (p = 0), and decrement the free bytes appropriately
pWanAdapter->P = 0;
}
pWanAdapter->Free -= increment;
if( pWanAdapter-> Size - pWanAdapter->Free >= pWanAdapter->MinToCopy )
{
SetEvent(pWanAdapter->hReadEvent);
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -