📄 wanpacket.cpp
字号:
/*
* Copyright (c) 2003 - 2005 NetGroup, Politecnico di Torino (Italy)
* Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#define _WIN32_DCOM
#include <tchar.h>
#include <winsock2.h>
#include <windows.h>
#include <crtdbg.h>
#include <eh.h>
HMODULE g_hModule = NULL;
#include <netmon.h>
#include "win_bpf.h"
#include "win_bpf_filter_init.h"
#include <packet32.h>
#include "wanpacket.h"
/*!
\brief Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
This structure is the most important for the functioning of WanPacket.dll.
This structure should be considered opaque by users.
*/
struct WAN_ADAPTER_INT
{
HBLOB hCaptureBlob; ///< Handle to the BLOB (the network adapter in the NetMon world) used to capture
CRITICAL_SECTION CriticalSection; ///< Used to synchronize access to this structure.
PUCHAR Buffer; ///< Pointer to the ring buffer used to capture packets.
DWORD C; ///< Zero-based index of the consumer in the ring buffer. It indicates the first free byte to be read.
DWORD P; ///< Zero-based index of the producer in the ring buffer. It indicates the first free byte to be written.
DWORD Free; ///< Number of the free bytes in the ring buffer.
DWORD Size; ///< Size of the ring buffer used to capture packets.
DWORD Dropped; ///< Number of packets that the current instance had to drop, from its opening. A packet is dropped if there is no more space to store it in the ring buffer.
DWORD Accepted; ///< Number of packets that the current capture instance has accepted, from its opening. A packet is accepted if it passes the bpf filter and fits in the ring buffer. Accepted packets are the ones that reach the application.
DWORD Received; ///< Number of packets received by current instance from its opening.
DWORD MinToCopy; ///< Minimum amount of data in the ring buffer that unlocks a read.
DWORD ReadTimeout; ///< Timeout after which a read is released, also if the amount of data in the ring buffer is less than MinToCopy.
HANDLE hReadEvent; ///< Pointer to the event on which the read calls on this instance must wait.
bpf_insn *FilterCode; ///< Pointer to the filtering pseudo-code associated with current instance of capture.
DWORD 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.
MEM_TYPE MemEx; ///< Memory used by the TME virtual co-processor
TME_CORE Tme; ///< Data structure containing the virtualization of the TME co-processor
IRTC *pIRTC; ///< Pointer to the NetMon IRTC COM interface used to capture packets.
};
#define ALIGN_TO_WORD(x) (((x) + 3)&~(3))
BOOLEAN WanPacketAddPacketToRingBuffer(PWAN_ADAPTER pWanAdapter, LPFRAME_DESCRIPTOR lpFrameDesc, DWORD SnapToCopy, struct timeval PacketTime);
DWORD WanPacketRemovePacketsFromRingBuffer(PWAN_ADAPTER pWanAdapter, PUCHAR Buffer, DWORD BuffSize);
BOOLEAN IsWindows2000();
#if 0
/*!
\brief The main dll function.
*/
#ifdef WPCAP_OEM
BOOLEAN LoadNdisNpp(DWORD Reason)
#else
BOOLEAN APIENTRY DllMain( HANDLE hModule, DWORD Reason, LPVOID lpReserved)
#endif // WPCAP_OEM
{
switch(Reason)
{
case DLL_PROCESS_ATTACH:
g_hModule = LoadLibrary("npp\\ndisnpp.dll");
break;
case DLL_PROCESS_DETACH:
if (g_hModule != NULL)
FreeLibrary(g_hModule);
break;
}
return TRUE;
}
#endif
/*!
\brief It returns the current time formatted as a timeval structure.
\return The current time formatted as a timeval structure.
*/
struct timeval WanPacketGetCurrentTime()
{
struct timeval tvReturn;
FILETIME FileTime;
GetSystemTimeAsFileTime(&FileTime);
tvReturn.tv_sec = (LONG)(((LARGE_INTEGER*)&FileTime)->QuadPart / 10000000);
tvReturn.tv_usec = (LONG)(((LARGE_INTEGER*)&FileTime)->QuadPart % 10000000 / 10);
return tvReturn;
}
/*!
\brief This is the callback used by the NetMon IRTC interface to pass the packets to the user.
\param Event. An UPDATE_EVENT structure containing the packets.
\return Not clearly defined by the NetMon IRTC MSDN documentation.
*/
DWORD WINAPI WanPacketReceiverCallback(UPDATE_EVENT Event)
{
DWORD i;
LPFRAMETABLE lpFrameTable;
LPFRAME_DESCRIPTOR lpFrameDesc;
PWAN_ADAPTER pWanAdapter;
u_int FilterResult;
struct time_conv TimeConv;
struct timeval PacketTime;
pWanAdapter = (PWAN_ADAPTER)Event.lpUserContext;
lpFrameTable = Event.lpFrameTable;
// the frame table can wrap the indices
for (i = lpFrameTable->StartIndex; i != lpFrameTable->EndIndex; (i == lpFrameTable->FrameTableLength) ? i=0: i ++ )
{
lpFrameDesc = &lpFrameTable->Frames[i];
PacketTime.tv_sec = (ULONG) (lpFrameDesc->TimeStamp / (__int64)1000000 - 11644473600);
PacketTime.tv_usec= (ULONG) (lpFrameDesc->TimeStamp % (__int64)1000000);
FORCE_TIME(&PacketTime, &TimeConv);
EnterCriticalSection( &pWanAdapter->CriticalSection );
pWanAdapter->Received ++;
FilterResult = bpf_filter(pWanAdapter->FilterCode,
lpFrameDesc->FramePointer,
lpFrameDesc->FrameLength,
lpFrameDesc->nBytesAvail,
&pWanAdapter->MemEx,
&pWanAdapter->Tme,
&TimeConv);
if ( pWanAdapter->Mode == PACKET_MODE_MON && FilterResult == 1 )
SetEvent( pWanAdapter->hReadEvent );
if (FilterResult == (u_int) -1 || FilterResult > lpFrameDesc->nBytesAvail )
FilterResult = lpFrameDesc->nBytesAvail;
if ( pWanAdapter->Mode == PACKET_MODE_STAT )
{
pWanAdapter->Npackets.QuadPart ++;
if ( lpFrameDesc->FrameLength < 60 )
pWanAdapter->Nbytes.QuadPart += 60;
else
pWanAdapter->Nbytes.QuadPart += lpFrameDesc->FrameLength;
// add preamble+SFD+FCS to the packet
// these values must be considered because are not part of the packet received from NDIS
pWanAdapter->Nbytes.QuadPart += 12;
}
if ( pWanAdapter->Mode == PACKET_MODE_CAPT && FilterResult > 0 )
{
if ( WanPacketAddPacketToRingBuffer(pWanAdapter, lpFrameDesc, FilterResult, PacketTime ) )
pWanAdapter->Accepted++;
else
pWanAdapter->Dropped++;
}
LeaveCriticalSection( &pWanAdapter->CriticalSection );
}
return NOERROR;
}
/*!
\brief Tries to open the wan (dialup, vpn...) adapter, and immediately closes it.
\return TRUE on success.
*/
BOOLEAN WanPacketTestAdapter()
{
PBLOB_TABLE pBlobTable = NULL;
HBLOB hFilterBlob = NULL;
BOOLEAN retVal;
DWORD i;
HRESULT hResult;
if ( g_hModule == NULL)
{
g_hModule = LoadLibrary("npp\\ndisnpp.dll");
}
if ( g_hModule == NULL)
{
return FALSE;
}
hResult = CoInitialize(NULL);
//
// if the calling thread has already initialized COM with a
// different threading model, we have this error
// however, we are able to support another threading model,
// so we try to initialize COM with another threading model.
// This new call should succeed with S_FALSE.
//
if (hResult == RPC_E_CHANGED_MODE)
{
hResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
//MULTITHREADED threading is only supported on Windows 2000
if (hResult == RPC_E_CHANGED_MODE && IsWindows2000())
{
hResult = CoInitializeEx(NULL, COINIT_MULTITHREADED);
}
}
if (hResult != S_OK && hResult != S_FALSE)
return FALSE;
if ( CreateBlob(&hFilterBlob) != NMERR_SUCCESS )
{
CoUninitialize();
return FALSE;
}
if ( SetBoolInBlob(hFilterBlob, OWNER_NPP, CATEGORY_CONFIG, TAG_INTERFACE_REALTIME_CAPTURE, TRUE) != NMERR_SUCCESS )
{
DestroyBlob( hFilterBlob);
CoUninitialize();
return FALSE;
}
if ( SetBoolInBlob(hFilterBlob, OWNER_NPP, CATEGORY_LOCATION, TAG_RAS, TRUE) != NMERR_SUCCESS )
{
DestroyBlob( hFilterBlob);
CoUninitialize();
return FALSE;
}
if ( GetNPPBlobTable(hFilterBlob, &pBlobTable) != NMERR_SUCCESS )
{
DestroyBlob( hFilterBlob);
CoUninitialize();
return FALSE;
}
DestroyBlob (hFilterBlob);
if (pBlobTable->dwNumBlobs == 1)
retVal = TRUE;
else
retVal = FALSE;
for ( i = 0 ; i < pBlobTable->dwNumBlobs ; i++ )
DestroyBlob(pBlobTable->hBlobs[i]);
GlobalFree(pBlobTable);
CoUninitialize();
return retVal;
}
/*!
\brief Returns true if the system is running windows 2000
\return TRUE if the system is running windows 2000. FALSE otherwise.
*/
BOOLEAN IsWindows2000()
{
OSVERSIONINFOEX osvi;
BOOL bOsVersionInfoEx;
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
// If that fails, try using the OSVERSIONINFO structure.
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi);
if( !bOsVersionInfoEx )
{
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
return FALSE;
}
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
//windows 2000
return TRUE;
return FALSE;
}
/*!
\brief Opens the wan (dialup, vpn...) adapter.
\return If the function succeeds, the return value is the pointer to a properly initialized WAN_ADAPTER structure,
otherwise the return value is NULL.
*/
PWAN_ADAPTER WanPacketOpenAdapter()
{
PWAN_ADAPTER pWanAdapter = NULL;
PBLOB_TABLE pBlobTable = NULL;
HBLOB hFilterBlob = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -