📄 packet32.c
字号:
/*
* Copyright (c) 1999 - 2003
* NetGroup, Politecnico di Torino (Italy)
* 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 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 UNICODE 1
#include <packet32.h>
#include <windows.h>
#include <windowsx.h>
#include <ntddndis.h>
/// Title of error windows
TCHAR szWindowTitle[] = TEXT("PACKET.DLL");
#if _DBG
#define ODS(_x) OutputDebugString(TEXT(_x))
#define ODSEx(_x, _y)
#else
#ifdef _DEBUG_TO_FILE
#include <stdio.h>
/*!
\brief Macro to print a debug string. The behavior differs depending on the debug level
*/
#define ODS(_x) { \
FILE *f; \
f = fopen("winpcap_debug.txt", "a"); \
fprintf(f, "%s", _x); \
fclose(f); \
}
/*!
\brief Macro to print debug data with the printf convention. The behavior differs depending on
the debug level
*/
#define ODSEx(_x, _y) { \
FILE *f; \
f = fopen("winpcap_debug.txt", "a"); \
fprintf(f, _x, _y); \
fclose(f); \
}
LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
#else
#define ODS(_x)
#define ODSEx(_x, _y)
#endif
#endif
//service handles
SC_HANDLE scmHandle = NULL;
SC_HANDLE srvHandle = NULL;
LPCTSTR NPFServiceName = TEXT("NPF");
LPCTSTR NPFServiceDesc = TEXT("Netgroup Packet Filter");
LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\CurrentControlSet\\Services\\NPF");
LPCTSTR NPFDriverPath = TEXT("system32\\drivers\\npf.sys");
//---------------------------------------------------------------------------
/*!
\brief The main dll function.
*/
BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
{
BOOLEAN Status=TRUE;
switch ( Reason )
{
case DLL_PROCESS_ATTACH:
ODS("************Packet32: DllMain************\n");
#ifdef _DEBUG_TO_FILE
// dump a bunch of registry keys useful for debug to file
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
"adapters.reg");
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip",
"tcpip.reg");
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\NPF",
"npf.reg");
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services",
"services.reg");
#endif
break;
case DLL_PROCESS_DETACH:
break;
default:
break;
}
return Status;
}
/*!
\brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
\param string The string to convert.
\return The converted string.
*/
WCHAR* SChar2WChar(char* string)
{
WCHAR* TmpStr;
TmpStr=(WCHAR*) malloc ((strlen(string)+2)*sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, string, -1, TmpStr, (strlen(string)+2));
return TmpStr;
}
/*!
\brief Sets the maximum possible lookahead buffer for the driver's Packet_tap() function.
\param AdapterObject Handle to the service control manager.
\return If the function succeeds, the return value is nonzero.
The lookahead buffer is the portion of packet that Packet_tap() can access from the NIC driver's memory
without performing a copy. This function tries to increase the size of that buffer.
*/
BOOLEAN PacketSetMaxLookaheadsize (LPADAPTER AdapterObject)
{
BOOLEAN Status;
ULONG IoCtlBufferLength=(sizeof(PACKET_OID_DATA)+sizeof(ULONG)-1);
PPACKET_OID_DATA OidData;
OidData=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,IoCtlBufferLength);
if (OidData == NULL) {
ODS("PacketSetMaxLookaheadsize failed\n");
return FALSE;
}
//set the size of the lookahead buffer to the maximum available by the the NIC driver
OidData->Oid=OID_GEN_MAXIMUM_LOOKAHEAD;
OidData->Length=sizeof(ULONG);
Status=PacketRequest(AdapterObject,FALSE,OidData);
OidData->Oid=OID_GEN_CURRENT_LOOKAHEAD;
Status=PacketRequest(AdapterObject,TRUE,OidData);
GlobalFreePtr(OidData);
return Status;
}
/*!
\brief Retrieves the event associated in the driver with a capture instance and stores it in an
_ADAPTER structure.
\param AdapterObject Handle to the service control manager.
\return If the function succeeds, the return value is nonzero.
This function is used by PacketOpenAdapter() to retrieve the read event from the driver by means of an ioctl
call and set it in the _ADAPTER structure pointed by AdapterObject.
*/
BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
{
DWORD BytesReturned;
TCHAR EventName[39];
// this tells the terminal service to retrieve the event from the global namespace
wcsncpy(EventName,L"Global\\",sizeof(L"Global\\"));
// retrieve the name of the shared event from the driver
if(DeviceIoControl(AdapterObject->hFile,pBIOCEVNAME,NULL,0,EventName+7,13*sizeof(TCHAR),&BytesReturned,NULL)==FALSE) return FALSE;
EventName[20]=0; // terminate the string
// open the shared event
AdapterObject->ReadEvent=CreateEvent(NULL,
TRUE,
FALSE,
EventName);
// in NT4 "Global\" is not automatically ignored: try to use simply the event name
if(GetLastError()!=ERROR_ALREADY_EXISTS){
if(AdapterObject->ReadEvent != NULL)
CloseHandle(AdapterObject->ReadEvent);
// open the shared event
AdapterObject->ReadEvent=CreateEvent(NULL,
TRUE,
FALSE,
EventName+7);
}
if(AdapterObject->ReadEvent==NULL || GetLastError()!=ERROR_ALREADY_EXISTS){
ODS("PacketSetReadEvt: error retrieving the event from the kernel\n");
return FALSE;
}
AdapterObject->ReadTimeOut=0;
return TRUE;
}
/*!
\brief Installs the NPF device driver.
\param ascmHandle Handle to the service control manager.
\param ascmHandle A pointer to a handle that will receive the pointer to the driver's service.
\return If the function succeeds, the return value is nonzero.
This function installs the driver's service in the system using the CreateService function.
*/
BOOL PacketInstallDriver(SC_HANDLE ascmHandle,SC_HANDLE *srvHandle)
{
BOOL result = FALSE;
ULONG err;
ODS("installdriver\n");
*srvHandle = CreateService(ascmHandle,
NPFServiceName,
NPFServiceDesc,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
NPFDriverPath,
NULL, NULL, NULL, NULL, NULL);
if (*srvHandle == NULL)
{
if (GetLastError() == ERROR_SERVICE_EXISTS)
{
//npf.sys already existed
result = TRUE;
}
}
else
{
//Created service for npf.sys
result = TRUE;
}
if (result == TRUE)
if (*srvHandle != NULL)
CloseServiceHandle(*srvHandle);
if(result == FALSE){
err = GetLastError();
if(err != 2)
ODSEx("PacketInstallDriver failed, Error=%d\n",err);
}
return result;
}
/*!
\brief Convert a Unicode dotted-quad to a 32-bit IP address.
\param cp A string containing the address.
\return the converted 32-bit numeric address.
Doesn't check to make sure the address is valid.
*/
ULONG inet_addrU(const WCHAR *cp)
{
ULONG val, part;
WCHAR c;
int i;
val = 0;
for (i = 0; i < 4; i++) {
part = 0;
while ((c = *cp++) != '\0' && c != '.') {
if (c < '0' || c > '9')
return -1;
part = part*10 + (c - '0');
}
if (part > 255)
return -1;
val = val | (part << i*8);
if (i == 3) {
if (c != '\0')
return -1; // extra gunk at end of string
} else {
if (c == '\0')
return -1; // string ends early
}
}
return val;
}
/*!
\brief Dumps a registry key to disk in text format. Uses regedit.
\param KeyName Name of the ket to dump. All its subkeys will be saved recursively.
\param FileName Name of the file that will contain the dump.
\return If the function succeeds, the return value is nonzero.
For debugging purposes, we use this function to obtain some registry keys from the user's machine.
*/
#ifdef _DEBUG_TO_FILE
LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName)
{
CHAR Command[256];
strcpy(Command, "regedit /e ");
strcat(Command, FileName);
strcat(Command, " ");
strcat(Command, KeyName);
/// Let regedit do the dirt work for us
system(Command);
return TRUE;
}
#endif
//---------------------------------------------------------------------------
// PUBLIC API
//---------------------------------------------------------------------------
/** @ingroup packetapi
* @{
*/
/** @defgroup packet32 Packet.dll exported functions and variables
* @{
*/
/// Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function.
char PacketLibraryVersion[] = "3.0.1 alpha";
/*!
\brief Returns a string with the dll version.
\return A char pointer to the version of the library.
*/
PCHAR PacketGetVersion(){
return PacketLibraryVersion;
}
/*!
\brief Returns information about the MAC type of an adapter.
\param AdapterObject The adapter on which information is needed.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -