2002-06-19 15:50:29 +00:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 1999, 2000
|
|
|
|
|
* Politecnico di Torino. All rights reserved.
|
|
|
|
|
*
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
|
* modification, are permitted provided that: (1) source code distributions
|
|
|
|
|
* retain the above copyright notice and this paragraph in its entirety, (2)
|
|
|
|
|
* distributions including binary code include the above copyright notice and
|
|
|
|
|
* this paragraph in its entirety in the documentation or other materials
|
|
|
|
|
* provided with the distribution, and (3) all advertising materials mentioning
|
|
|
|
|
* features or use of this software display the following acknowledgement:
|
|
|
|
|
* ``This product includes software developed by the Politecnico
|
|
|
|
|
* di Torino, and its contributors.'' Neither the name of
|
|
|
|
|
* the University 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
|
|
|
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
|
|
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#define UNICODE 1
|
|
|
|
|
|
|
|
|
|
#include <windows.h>
|
2005-12-01 21:37:19 +00:00
|
|
|
|
#include <ntddndis.h>
|
2003-11-14 17:13:36 +00:00
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2003-01-17 13:09:43 +00:00
|
|
|
|
#include <packet32.h>
|
2002-09-24 15:08:14 +00:00
|
|
|
|
#include "trace.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****** KERNEL Macro APIs ******************************************************/
|
|
|
|
|
|
|
|
|
|
#define GetInstanceModule(hInst) (HMODULE)(hInst)
|
|
|
|
|
#define GlobalPtrHandle(lp) ((HGLOBAL)GlobalHandle(lp))
|
|
|
|
|
#define GlobalLockPtr(lp) ((BOOL)GlobalLock(GlobalPtrHandle(lp)))
|
|
|
|
|
#define GlobalUnlockPtr(lp) GlobalUnlock(GlobalPtrHandle(lp))
|
|
|
|
|
#define GlobalAllocPtr(flags, cb) (GlobalLock(GlobalAlloc((flags), (cb))))
|
|
|
|
|
#define GlobalReAllocPtr(lp, cbNew, flags) (GlobalUnlockPtr(lp), GlobalLock(GlobalReAlloc(GlobalPtrHandle(lp) , (cbNew), (flags))))
|
|
|
|
|
#define GlobalFreePtr(lp) (GlobalUnlockPtr(lp), (BOOL)(ULONG_PTR)GlobalFree(GlobalPtrHandle(lp)))
|
|
|
|
|
|
|
|
|
|
#undef GMEM_MOVEABLE
|
|
|
|
|
#define GMEM_MOVEABLE 0
|
|
|
|
|
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
/// Title of error windows
|
|
|
|
|
TCHAR szWindowTitle[] = TEXT("PACKET.DLL");
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
#if DBG
|
2002-06-19 15:50:29 +00:00
|
|
|
|
#define ODS(_x) OutputDebugString(TEXT(_x))
|
2002-09-24 15:08:14 +00:00
|
|
|
|
//#define ODSEx(_x, _y)
|
|
|
|
|
#define ODSEx TRACE
|
2002-06-19 15:50:29 +00:00
|
|
|
|
#else
|
|
|
|
|
#ifdef _DEBUG_TO_FILE
|
|
|
|
|
#include <stdio.h>
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Macro to print a debug string. The behavior differs depending on the debug level
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
#define ODS(_x) { \
|
|
|
|
|
FILE *f; \
|
|
|
|
|
f = fopen("winpcap_debug.txt", "a"); \
|
|
|
|
|
fprintf(f, "%s", _x); \
|
|
|
|
|
fclose(f); \
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Macro to print debug data with the printf convention. The behavior differs depending on
|
2002-09-24 15:08:14 +00:00
|
|
|
|
the debug level
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
#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
|
2007-10-19 23:21:45 +00:00
|
|
|
|
#define ODS(_x)
|
2002-06-19 15:50:29 +00:00
|
|
|
|
#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 NPFDriverName = TEXT("\\npf.sys");
|
2002-09-24 15:08:14 +00:00
|
|
|
|
LPCTSTR NPFRegistryLocation = TEXT("SYSTEM\\ControlSet001\\Services\\NPF");
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief The main dll function.
|
|
|
|
|
*/
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOL APIENTRY DllMain (HANDLE DllHandle,DWORD Reason,LPVOID lpReserved)
|
|
|
|
|
{
|
|
|
|
|
BOOLEAN Status=TRUE;
|
|
|
|
|
|
|
|
|
|
switch ( Reason )
|
|
|
|
|
{
|
|
|
|
|
case DLL_PROCESS_ATTACH:
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("\n************Packet32: DllMain************\n");
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
#ifdef _DEBUG_TO_FILE
|
|
|
|
|
// dump a bunch of registry keys useful for debug to file
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}",
|
2002-06-19 15:50:29 +00:00
|
|
|
|
"adapters.reg");
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\Tcpip",
|
2002-06-19 15:50:29 +00:00
|
|
|
|
"tcpip.reg");
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services\\NPF",
|
2002-06-19 15:50:29 +00:00
|
|
|
|
"npf.reg");
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PacketDumpRegistryKey("HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Services",
|
2002-06-19 15:50:29 +00:00
|
|
|
|
"services.reg");
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Converts an ASCII string to UNICODE. Uses the MultiByteToWideChar() system function.
|
|
|
|
|
\param string The string to convert.
|
|
|
|
|
\return The converted string.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\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.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Retrieves the event associated in the driver with a capture instance and stores it in an
|
2002-09-24 15:08:14 +00:00
|
|
|
|
_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.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
BOOLEAN PacketSetReadEvt(LPADAPTER AdapterObject)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
WCHAR EventName[39];
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
// 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
|
2002-09-24 15:08:14 +00:00
|
|
|
|
AdapterObject->ReadEvent=CreateEventW(NULL,
|
2002-06-19 15:50:29 +00:00
|
|
|
|
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);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// open the shared event
|
2002-09-24 15:08:14 +00:00
|
|
|
|
AdapterObject->ReadEvent=CreateEventW(NULL,
|
2002-06-19 15:50:29 +00:00
|
|
|
|
TRUE,
|
|
|
|
|
FALSE,
|
|
|
|
|
EventName+7);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
}
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\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.
|
|
|
|
|
\param driverPath The full path of the .sys file to load.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
|
|
|
|
This function installs the driver's service in the system using the CreateService function.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
BOOL PacketInstallDriver(SC_HANDLE ascmHandle, SC_HANDLE* srvHandle, TCHAR* driverPath)
|
2002-06-19 15:50:29 +00:00
|
|
|
|
{
|
|
|
|
|
BOOL result = FALSE;
|
|
|
|
|
ULONG err;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
ODS("installdriver\n");
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (GetFileAttributes(driverPath) != 0xffffffff) {
|
2007-10-19 23:21:45 +00:00
|
|
|
|
*srvHandle = CreateService(ascmHandle,
|
2002-06-19 15:50:29 +00:00
|
|
|
|
NPFServiceName,
|
|
|
|
|
NPFServiceDesc,
|
|
|
|
|
SERVICE_ALL_ACCESS,
|
|
|
|
|
SERVICE_KERNEL_DRIVER,
|
|
|
|
|
SERVICE_DEMAND_START,
|
|
|
|
|
SERVICE_ERROR_NORMAL,
|
|
|
|
|
driverPath,
|
|
|
|
|
NULL, NULL, NULL, NULL, NULL);
|
|
|
|
|
if (*srvHandle == NULL) {
|
|
|
|
|
if (GetLastError() == ERROR_SERVICE_EXISTS) {
|
|
|
|
|
//npf.sys already existed
|
|
|
|
|
result = TRUE;
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
//Created service for npf.sys
|
|
|
|
|
result = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (result == TRUE) {
|
|
|
|
|
if (*srvHandle != NULL) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
CloseServiceHandle(*srvHandle);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (result == FALSE){
|
2002-06-19 15:50:29 +00:00
|
|
|
|
err = GetLastError();
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (err != 2) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODSEx("PacketInstallDriver failed, Error=%d\n",err);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
}
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
return result;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\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.
|
|
|
|
|
*/
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
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)
|
2007-10-19 23:21:45 +00:00
|
|
|
|
return -1;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
val = val | (part << i*8);
|
|
|
|
|
if (i == 3) {
|
|
|
|
|
if (c != '\0')
|
2007-10-19 23:21:45 +00:00
|
|
|
|
return -1; // extra gunk at end of string
|
2002-06-19 15:50:29 +00:00
|
|
|
|
} else {
|
|
|
|
|
if (c == '\0')
|
2007-10-19 23:21:45 +00:00
|
|
|
|
return -1; // string ends early
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\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.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/** @ingroup packetapi
|
|
|
|
|
* @{
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** @defgroup packet32 Packet.dll exported functions and variables
|
|
|
|
|
* @{
|
|
|
|
|
*/
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
/// Current packet.dll Version. It can be retrieved directly or through the PacketGetVersion() function.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
char PacketLibraryVersion[] = "2.3";
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Returns a string with the dll version.
|
|
|
|
|
\return A char pointer to the version of the library.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
PCHAR PacketGetVersion(){
|
|
|
|
|
return PacketLibraryVersion;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Returns information about the MAC type of an adapter.
|
|
|
|
|
\param AdapterObject The adapter on which information is needed.
|
|
|
|
|
\param type Pointer to a NetType structure that will be filled by the function.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero, otherwise the return value is zero.
|
|
|
|
|
|
|
|
|
|
This function return the link layer technology and the speed (in bps) of an opened adapter.
|
|
|
|
|
The LinkType field of the type parameter can have one of the following values:
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- NdisMedium802_3: Ethernet (802.3)
|
|
|
|
|
- NdisMediumWan: WAN
|
|
|
|
|
- NdisMedium802_5: Token Ring (802.5)
|
|
|
|
|
- NdisMediumFddi: FDDI
|
|
|
|
|
- NdisMediumAtm: ATM
|
|
|
|
|
- NdisMediumArcnet878_2: ARCNET (878.2)
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type)
|
|
|
|
|
{
|
|
|
|
|
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("PacketGetNetType failed\n");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
//get the link-layer type
|
|
|
|
|
OidData->Oid = OID_GEN_MEDIA_IN_USE;
|
|
|
|
|
OidData->Length = sizeof (ULONG);
|
|
|
|
|
Status = PacketRequest(AdapterObject,FALSE,OidData);
|
|
|
|
|
type->LinkType=*((UINT*)OidData->Data);
|
|
|
|
|
|
|
|
|
|
//get the link-layer speed
|
|
|
|
|
OidData->Oid = OID_GEN_LINK_SPEED;
|
|
|
|
|
OidData->Length = sizeof (ULONG);
|
|
|
|
|
Status = PacketRequest(AdapterObject,FALSE,OidData);
|
|
|
|
|
type->LinkSpeed=*((UINT*)OidData->Data)*100;
|
|
|
|
|
GlobalFreePtr (OidData);
|
|
|
|
|
|
|
|
|
|
ODSEx("Media:%d ",type->LinkType);
|
|
|
|
|
ODSEx("Speed=%d\n",type->LinkSpeed);
|
|
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Stops and unloads the WinPcap device driver.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero, otherwise it is zero.
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
This function can be used to unload the driver from memory when the application no more needs it.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
Note that the driver is physically stopped and unloaded only when all the files on its devices
|
2002-09-24 15:08:14 +00:00
|
|
|
|
are closed, i.e. when all the applications that use WinPcap close all their adapters.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOL PacketStopDriver()
|
|
|
|
|
{
|
|
|
|
|
SC_HANDLE scmHandle;
|
|
|
|
|
SC_HANDLE schService;
|
|
|
|
|
BOOL ret;
|
|
|
|
|
SERVICE_STATUS serviceStatus;
|
|
|
|
|
|
|
|
|
|
scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if(scmHandle != NULL){
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
schService = OpenService (scmHandle,
|
|
|
|
|
NPFServiceName,
|
|
|
|
|
SERVICE_ALL_ACCESS
|
|
|
|
|
);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (schService != NULL)
|
|
|
|
|
{
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ret = ControlService (schService,
|
|
|
|
|
SERVICE_CONTROL_STOP,
|
|
|
|
|
&serviceStatus
|
|
|
|
|
);
|
|
|
|
|
if (!ret)
|
|
|
|
|
{
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
CloseServiceHandle (schService);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
CloseServiceHandle(scmHandle);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Opens an adapter.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param AdapterName A string containing the name of the device to open.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Use the PacketGetAdapterNames() function to retrieve the list of available devices.
|
|
|
|
|
\return If the function succeeds, the return value is the pointer to a properly initialized ADAPTER object,
|
|
|
|
|
otherwise the return value is NULL.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
This function tries to load and start the packet driver at the first invocation. In this way,
|
2002-09-24 15:08:14 +00:00
|
|
|
|
the management of the driver is transparent to the application, that simply needs to open an adapter to start
|
|
|
|
|
WinPcap.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
|
|
|
|
\note the Windows 95 version of the NPF driver works with the ASCII string format, while the Windows NT
|
|
|
|
|
version works with UNICODE. Therefore, AdapterName \b should be an ASCII string in Windows 95, and a UNICODE
|
|
|
|
|
string in Windows NT. This difference is not a problem if the string pointed by AdapterName was obtained
|
2002-09-24 15:08:14 +00:00
|
|
|
|
through the PacketGetAdapterNames function, because it returns the names of the adapters in the proper format.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
Problems can arise in Windows NT when the string is obtained from ANSI C functions like scanf, because they
|
|
|
|
|
use the ASCII format. Since this could be a relevant problem during the porting of command-line applications
|
2002-09-24 15:08:14 +00:00
|
|
|
|
from UNIX, we included in the Windows NT version of PacketOpenAdapter the ability to detect ASCII strings and
|
2007-10-19 23:21:45 +00:00
|
|
|
|
convert them to UNICODE before sending them to the device driver. Therefore PacketOpenAdapter in Windows NT
|
|
|
|
|
accepts both the ASCII and the UNICODE format. If a ASCII string is received, it is converted to UNICODE
|
2002-09-24 15:08:14 +00:00
|
|
|
|
by PACKET.DLL before being passed to the driver.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
LPADAPTER PacketOpenAdapter(LPTSTR AdapterName)
|
|
|
|
|
{
|
|
|
|
|
LPADAPTER lpAdapter;
|
|
|
|
|
BOOLEAN Result;
|
|
|
|
|
char *AdapterNameA;
|
|
|
|
|
WCHAR *AdapterNameU;
|
|
|
|
|
DWORD error;
|
|
|
|
|
SC_HANDLE svcHandle = NULL;
|
|
|
|
|
TCHAR driverPath[512];
|
|
|
|
|
TCHAR WinPath[256];
|
|
|
|
|
LONG KeyRes;
|
|
|
|
|
HKEY PathKey;
|
|
|
|
|
SERVICE_STATUS SStat;
|
|
|
|
|
BOOLEAN QuerySStat;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
WCHAR SymbolicLink[128];
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
ODSEx("PacketOpenAdapter: trying to open the adapter=%S\n",AdapterName);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
scmHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
|
|
|
|
if(scmHandle == NULL){
|
|
|
|
|
error = GetLastError();
|
|
|
|
|
ODSEx("OpenSCManager failed! Error=%d\n", error);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
*driverPath = 0;
|
|
|
|
|
GetCurrentDirectory(512, driverPath);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
wsprintf(driverPath + wcslen(driverPath), NPFDriverName);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// check if the NPF registry key is already present
|
|
|
|
|
// this means that the driver is already installed and that we don't need to call PacketInstallDriver
|
|
|
|
|
KeyRes=RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
|
|
|
NPFRegistryLocation,
|
|
|
|
|
0,
|
|
|
|
|
KEY_READ,
|
|
|
|
|
&PathKey);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if(KeyRes != ERROR_SUCCESS){
|
|
|
|
|
Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
Result = TRUE;
|
|
|
|
|
RegCloseKey(PathKey);
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (Result) {
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
srvHandle = OpenService(scmHandle, NPFServiceName, SERVICE_START | SERVICE_QUERY_STATUS );
|
|
|
|
|
if (srvHandle != NULL){
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
QuerySStat = QueryServiceStatus(srvHandle, &SStat);
|
|
|
|
|
ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING){
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("Calling startservice\n");
|
2007-10-19 23:21:45 +00:00
|
|
|
|
if (StartService(srvHandle, 0, NULL)==0){
|
2002-06-19 15:50:29 +00:00
|
|
|
|
error = GetLastError();
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (error!=ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS){
|
2002-06-19 15:50:29 +00:00
|
|
|
|
SetLastError(error);
|
|
|
|
|
if (scmHandle != NULL) CloseServiceHandle(scmHandle);
|
|
|
|
|
error = GetLastError();
|
|
|
|
|
ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
}
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
error = GetLastError();
|
|
|
|
|
ODSEx("OpenService failed! Error=%d", error);
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
|
|
|
|
if (GetSystemDirectory(WinPath, sizeof(WinPath)/sizeof(TCHAR)) == 0) {
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
wsprintf(driverPath, TEXT("%s\\drivers%s"), WinPath, NPFDriverName);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (KeyRes != ERROR_SUCCESS) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
Result = PacketInstallDriver(scmHandle,&svcHandle,driverPath);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
Result = TRUE;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
}
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (Result) {
|
|
|
|
|
srvHandle = OpenService(scmHandle,NPFServiceName,SERVICE_START);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (srvHandle != NULL) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
QuerySStat = QueryServiceStatus(srvHandle, &SStat);
|
|
|
|
|
ODSEx("The status of the driver is:%d\n",SStat.dwCurrentState);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (!QuerySStat || SStat.dwCurrentState != SERVICE_RUNNING) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("Calling startservice\n");
|
2007-10-19 23:21:45 +00:00
|
|
|
|
if (StartService(srvHandle, 0, NULL) == 0) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
error = GetLastError();
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (error != ERROR_SERVICE_ALREADY_RUNNING && error!=ERROR_ALREADY_EXISTS) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
SetLastError(error);
|
|
|
|
|
if (scmHandle != NULL) CloseServiceHandle(scmHandle);
|
|
|
|
|
ODSEx("PacketOpenAdapter: StartService failed, Error=%d\n",error);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
error = GetLastError();
|
|
|
|
|
ODSEx("OpenService failed! Error=%d", error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (scmHandle != NULL) CloseServiceHandle(scmHandle);
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
AdapterNameA = (char*)AdapterName;
|
|
|
|
|
if (AdapterNameA[1] != 0) { // ASCII
|
|
|
|
|
AdapterNameU = SChar2WChar(AdapterNameA);
|
|
|
|
|
AdapterName = AdapterNameU;
|
|
|
|
|
} else { // Unicode
|
|
|
|
|
AdapterNameU = NULL;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
lpAdapter = (LPADAPTER)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(ADAPTER));
|
|
|
|
|
if (lpAdapter == NULL) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("PacketOpenAdapter: GlobalAlloc Failed\n");
|
2002-09-24 15:08:14 +00:00
|
|
|
|
error = GetLastError();
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (AdapterNameU != NULL) free(AdapterNameU);
|
|
|
|
|
//set the error to the one on which we failed
|
|
|
|
|
SetLastError(error);
|
|
|
|
|
ODS("PacketOpenAdapter: Failed to allocate the adapter structure\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
lpAdapter->NumWrites = 1;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
wsprintf(SymbolicLink,TEXT("\\\\.\\%s%s"), DOSNAMEPREFIX, &AdapterName[8]);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
// Copy only the bytes that fit in the adapter structure.
|
|
|
|
|
// Note that lpAdapter->SymbolicLink is present for backward compatibility but will
|
|
|
|
|
// never be used by the apps
|
|
|
|
|
memcpy(lpAdapter->SymbolicLink, (PCHAR)SymbolicLink, MAX_LINK_NAME_LENGTH);
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
//try if it is possible to open the adapter immediately
|
2002-09-24 15:08:14 +00:00
|
|
|
|
lpAdapter->hFile = CreateFile(SymbolicLink,GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
|
2002-09-24 15:08:14 +00:00
|
|
|
|
ODSEx("PacketOpenAdapter: CreateFile(%S) successfull\n", SymbolicLink);
|
|
|
|
|
if (PacketSetReadEvt(lpAdapter) == FALSE) {
|
|
|
|
|
error = GetLastError();
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("PacketOpenAdapter: Unable to open the read event\n");
|
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
GlobalFreePtr(lpAdapter);
|
|
|
|
|
//set the error to the one on which we failed
|
|
|
|
|
SetLastError(error);
|
|
|
|
|
ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=%d\n",error);
|
|
|
|
|
return NULL;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
PacketSetMaxLookaheadsize(lpAdapter);
|
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
return lpAdapter;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
//this is probably the first request on the packet driver.
|
2002-06-19 15:50:29 +00:00
|
|
|
|
//We must create the dos device and set the access rights on it
|
2002-09-24 15:08:14 +00:00
|
|
|
|
else {
|
|
|
|
|
Result = DefineDosDevice(DDD_RAW_TARGET_PATH,
|
|
|
|
|
&SymbolicLink[4],
|
|
|
|
|
AdapterName);
|
|
|
|
|
if (Result) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
ODSEx("PacketOpenAdapter: calling CreateFile(%S)\n", SymbolicLink);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
lpAdapter->hFile = CreateFile(
|
|
|
|
|
SymbolicLink,
|
|
|
|
|
GENERIC_WRITE | GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
if (lpAdapter->hFile != INVALID_HANDLE_VALUE) {
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (PacketSetReadEvt(lpAdapter) == FALSE) {
|
|
|
|
|
error = GetLastError();
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("PacketOpenAdapter: Unable to open the read event\n");
|
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
GlobalFreePtr(lpAdapter);
|
|
|
|
|
//set the error to the one on which we failed
|
|
|
|
|
SetLastError(error);
|
|
|
|
|
ODSEx("PacketOpenAdapter: PacketSetReadEvt failed, Error=1,%d\n",error);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
return NULL;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
PacketSetMaxLookaheadsize(lpAdapter);
|
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
return lpAdapter;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
|
|
|
|
ODS("PacketOpenAdapter: CreateFile failed\n");
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
|
|
|
|
ODSEx("PacketOpenAdapter: DefineDosDevice(%S) failed\n", &SymbolicLink[4]);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
error = GetLastError();
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
GlobalFreePtr(lpAdapter);
|
|
|
|
|
//set the error to the one on which we failed
|
|
|
|
|
SetLastError(error);
|
|
|
|
|
ODSEx("PacketOpenAdapter: CreateFile failed, Error=2,%d\n",error);
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Closes an adapter.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param lpAdapter the pointer to the adapter to close.
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PacketCloseAdapter closes the given adapter and frees the associated ADAPTER structure
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
VOID PacketCloseAdapter(LPADAPTER lpAdapter)
|
|
|
|
|
{
|
|
|
|
|
CloseHandle(lpAdapter->hFile);
|
|
|
|
|
SetEvent(lpAdapter->ReadEvent);
|
|
|
|
|
CloseHandle(lpAdapter->ReadEvent);
|
|
|
|
|
GlobalFreePtr(lpAdapter);
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Allocates a _PACKET structure.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\return On succeess, the return value is the pointer to a _PACKET structure otherwise the
|
2002-09-24 15:08:14 +00:00
|
|
|
|
return value is NULL.
|
|
|
|
|
|
|
|
|
|
The structure returned will be passed to the PacketReceivePacket() function to receive the
|
|
|
|
|
packets from the driver.
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\warning The Buffer field of the _PACKET structure is not set by this function.
|
|
|
|
|
The buffer \b must be allocated by the application, and associated to the PACKET structure
|
2002-09-24 15:08:14 +00:00
|
|
|
|
with a call to PacketInitPacket.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
LPPACKET PacketAllocatePacket(void)
|
|
|
|
|
{
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
LPPACKET lpPacket;
|
|
|
|
|
lpPacket = (LPPACKET)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT,sizeof(PACKET));
|
|
|
|
|
if (lpPacket == NULL) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("PacketAllocatePacket: GlobalAlloc Failed\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
return lpPacket;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Frees a _PACKET structure.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param lpPacket The structure to free.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\warning the user-allocated buffer associated with the _PACKET structure is not deallocated
|
2002-09-24 15:08:14 +00:00
|
|
|
|
by this function and \b must be explicitly deallocated by the programmer.
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
VOID PacketFreePacket(LPPACKET lpPacket)
|
|
|
|
|
{
|
|
|
|
|
GlobalFreePtr(lpPacket);
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Initializes a _PACKET structure.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param lpPacket The structure to initialize.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\param Buffer A pointer to a user-allocated buffer that will contain the captured data.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param Length the length of the buffer. This is the maximum buffer size that will be
|
2002-09-24 15:08:14 +00:00
|
|
|
|
transferred from the driver to the application using a single read.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\note the size of the buffer associated with the PACKET structure is a parameter that can sensibly
|
2002-09-24 15:08:14 +00:00
|
|
|
|
influence the performance of the capture process, since this buffer will contain the packets received
|
2007-10-19 23:21:45 +00:00
|
|
|
|
from the the driver. The driver is able to return several packets using a single read call
|
|
|
|
|
(see the PacketReceivePacket() function for details), and the number of packets transferable to the
|
2002-09-24 15:08:14 +00:00
|
|
|
|
application in a call is limited only by the size of the buffer associated with the PACKET structure
|
2007-10-19 23:21:45 +00:00
|
|
|
|
passed to PacketReceivePacket(). Therefore setting a big buffer with PacketInitPacket can noticeably
|
2002-09-24 15:08:14 +00:00
|
|
|
|
decrease the number of system calls, reducing the impcat of the capture process on the processor.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length)
|
|
|
|
|
{
|
|
|
|
|
lpPacket->Buffer = Buffer;
|
|
|
|
|
lpPacket->Length = Length;
|
|
|
|
|
lpPacket->ulBytesReceived = 0;
|
|
|
|
|
lpPacket->bIoComplete = FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Read data (packets or statistics) from the NPF driver.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter from which
|
2002-09-24 15:08:14 +00:00
|
|
|
|
the data is received.
|
|
|
|
|
\param lpPacket Pointer to a PACKET structure that will contain the data.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
|
2002-09-24 15:08:14 +00:00
|
|
|
|
older applications.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
The data received with this function can be a group of packets or a static on the network traffic,
|
|
|
|
|
depending on the working mode of the driver. The working mode can be set with the PacketSetMode()
|
|
|
|
|
function. Give a look at that function if you are interested in the format used to return statistics
|
2002-09-24 15:08:14 +00:00
|
|
|
|
values, here only the normal capture mode will be described.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
The number of packets received with this function is variable. It depends on the number of packets
|
|
|
|
|
currently stored in the driver<EFBFBD>s buffer, on the size of these packets and on the size of the buffer
|
|
|
|
|
associated to the lpPacket parameter. The following figure shows the format used by the driver to pass
|
|
|
|
|
packets to the application.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
|
|
|
|
|
\image html encoding.gif "method used to encode the packets"
|
|
|
|
|
|
|
|
|
|
Packets are stored in the buffer associated with the lpPacket _PACKET structure. The Length field of
|
|
|
|
|
that structure is updated with the amount of data copied in the buffer. Each packet has a header
|
2007-10-19 23:21:45 +00:00
|
|
|
|
consisting in a bpf_hdr structure that defines its length and contains its timestamp. A padding field
|
|
|
|
|
is used to word-align the data in the buffer (to speed up the access to the packets). The bh_datalen
|
|
|
|
|
and bh_hdrlen fields of the bpf_hdr structures should be used to extract the packets from the buffer.
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Examples can be seen either in the TestApp sample application (see the \ref packetsamps page) provided
|
|
|
|
|
in the developer's pack, or in the pcap_read() function of wpcap.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
|
|
|
|
|
{
|
|
|
|
|
BOOLEAN res;
|
|
|
|
|
if ((int)AdapterObject->ReadTimeOut != -1)
|
|
|
|
|
WaitForSingleObject(AdapterObject->ReadEvent, (AdapterObject->ReadTimeOut==0)?INFINITE:AdapterObject->ReadTimeOut);
|
|
|
|
|
res = ReadFile(AdapterObject->hFile, lpPacket->Buffer, lpPacket->Length, &lpPacket->ulBytesReceived,NULL);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Sends one (or more) copies of a packet to the network.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
|
2002-09-24 15:08:14 +00:00
|
|
|
|
send the packets.
|
|
|
|
|
\param lpPacket Pointer to a PACKET structure with the packet to send.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param Sync This parameter is deprecated and will be ignored. It is present for compatibility with
|
2002-09-24 15:08:14 +00:00
|
|
|
|
older applications.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
This function is used to send a raw packet to the network. 'Raw packet' means that the programmer
|
|
|
|
|
will have to include the protocol headers, since the packet is sent to the network 'as is'.
|
|
|
|
|
The CRC needs not to be calculated and put at the end of the packet, because it will be transparently
|
2002-09-24 15:08:14 +00:00
|
|
|
|
added by the network interface.
|
|
|
|
|
|
|
|
|
|
The behavior of this function is influenced by the PacketSetNumWrites() function. With PacketSetNumWrites(),
|
2007-10-19 23:21:45 +00:00
|
|
|
|
it is possible to change the number of times a single write must be repeated. The default is 1,
|
2002-09-24 15:08:14 +00:00
|
|
|
|
i.e. every call to PacketSendPacket() will correspond to one packet sent to the network. If this number is
|
2007-10-19 23:21:45 +00:00
|
|
|
|
greater than 1, for example 1000, every raw packet written by the application will be sent 1000 times on
|
|
|
|
|
the network. This feature mitigates the overhead of the context switches and therefore can be used to generate
|
|
|
|
|
high speed traffic. It is particularly useful for tools that test networks, routers, and servers and need
|
2002-09-24 15:08:14 +00:00
|
|
|
|
to obtain high network loads.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
The optimized sending process is still limited to one packet at a time: for the moment it cannot be used
|
2002-09-24 15:08:14 +00:00
|
|
|
|
to send a buffer with multiple packets.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\note The ability to write multiple packets is currently present only in the Windows NTx version of the
|
2002-09-24 15:08:14 +00:00
|
|
|
|
packet driver. In Windows 95/98/ME it is emulated at user level in packet.dll. This means that an application
|
2007-10-19 23:21:45 +00:00
|
|
|
|
that uses the multiple write method will run in Windows 9x as well, but its performance will be very low
|
2002-09-24 15:08:14 +00:00
|
|
|
|
compared to the one of WindowsNTx.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesTransfered;
|
|
|
|
|
return WriteFile(AdapterObject->hFile,lpPacket->Buffer,lpPacket->Length,&BytesTransfered,NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Sends a buffer of packets to the network.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure identifying the network adapter that will
|
2002-09-24 15:08:14 +00:00
|
|
|
|
send the packets.
|
|
|
|
|
\param PacketBuff Pointer to buffer with the packets to send.
|
|
|
|
|
\param Size Size of the buffer pointed by the PacketBuff argument.
|
|
|
|
|
\param Sync if TRUE, the packets are sent respecting the timestamps. If FALSE, the packets are sent as
|
|
|
|
|
fast as possible
|
|
|
|
|
\return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
|
|
|
|
|
error occurred during the send. The error can be caused by a driver/adapter problem or by an
|
|
|
|
|
inconsistent/bogus packet buffer.
|
|
|
|
|
|
|
|
|
|
This function is used to send a buffer of raw packets to the network. The buffer can contain an arbitrary
|
|
|
|
|
number of raw packets, each of which preceded by a dump_bpf_hdr structure. The dump_bpf_hdr is the same used
|
|
|
|
|
by WinPcap and libpcap to store the packets in a file, therefore sending a capture file is straightforward.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
'Raw packets' 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
|
2002-09-24 15:08:14 +00:00
|
|
|
|
transparently added by the network interface.
|
|
|
|
|
|
|
|
|
|
\note Using this function if more efficient than issuing a series of PacketSendPacket(), because the packets are
|
|
|
|
|
buffered in the kernel driver, so the number of context switches is reduced.
|
|
|
|
|
|
|
|
|
|
\note When Sync is set to TRUE, the packets are synchronized in the kerenl with a high precision timestamp.
|
|
|
|
|
This requires a remarkable amount of CPU, but allows to send the packets with a precision of some microseconds
|
2007-10-19 23:21:45 +00:00
|
|
|
|
(depending on the precision of the performance counter of the machine). Such a precision cannot be reached
|
2002-09-24 15:08:14 +00:00
|
|
|
|
sending the packets separately with PacketSendPacket().
|
|
|
|
|
*/
|
|
|
|
|
INT PacketSendPackets(LPADAPTER AdapterObject, PVOID PacketBuff, ULONG Size, BOOLEAN Sync)
|
|
|
|
|
{
|
|
|
|
|
BOOLEAN Res;
|
|
|
|
|
DWORD BytesTransfered, TotBytesTransfered=0;
|
|
|
|
|
struct timeval BufStartTime;
|
|
|
|
|
LARGE_INTEGER StartTicks, CurTicks, TargetTicks, TimeFreq;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ODS("PacketSendPackets");
|
|
|
|
|
|
|
|
|
|
// Obtain starting timestamp of the buffer
|
|
|
|
|
BufStartTime.tv_sec = ((struct timeval*)(PacketBuff))->tv_sec;
|
|
|
|
|
BufStartTime.tv_usec = ((struct timeval*)(PacketBuff))->tv_usec;
|
|
|
|
|
|
|
|
|
|
// Retrieve the reference time counters
|
|
|
|
|
QueryPerformanceCounter(&StartTicks);
|
|
|
|
|
QueryPerformanceFrequency(&TimeFreq);
|
|
|
|
|
|
|
|
|
|
CurTicks.QuadPart = StartTicks.QuadPart;
|
|
|
|
|
|
|
|
|
|
do{
|
|
|
|
|
// Send the data to the driver
|
|
|
|
|
Res = DeviceIoControl(AdapterObject->hFile,
|
|
|
|
|
(Sync)?pBIOCSENDPACKETSSYNC:pBIOCSENDPACKETSNOSYNC,
|
|
|
|
|
(PCHAR)PacketBuff + TotBytesTransfered,
|
|
|
|
|
Size - TotBytesTransfered,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
&BytesTransfered,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
TotBytesTransfered += BytesTransfered;
|
|
|
|
|
|
|
|
|
|
// calculate the time interval to wait before sending the next packet
|
|
|
|
|
TargetTicks.QuadPart = StartTicks.QuadPart +
|
|
|
|
|
(LONGLONG)
|
|
|
|
|
((((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_sec - BufStartTime.tv_sec) * 1000000 +
|
|
|
|
|
(((struct timeval*)((PCHAR)PacketBuff + TotBytesTransfered))->tv_usec - BufStartTime.tv_usec)) *
|
|
|
|
|
(TimeFreq.QuadPart) / 1000000;
|
|
|
|
|
|
|
|
|
|
// Exit from the loop on termination or error
|
|
|
|
|
if(TotBytesTransfered >= Size || Res != TRUE)
|
|
|
|
|
break;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
// Wait until the time interval has elapsed
|
|
|
|
|
while( CurTicks.QuadPart <= TargetTicks.QuadPart )
|
|
|
|
|
QueryPerformanceCounter(&CurTicks);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
while(TRUE);
|
|
|
|
|
|
|
|
|
|
return TotBytesTransfered;
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
/*!
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\brief Defines the minimum amount of data that will be received in a read.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure
|
|
|
|
|
\param nbytes the minimum amount of data in the kernel buffer that will cause the driver to
|
|
|
|
|
release a read on this adapter.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
In presence of a large value for nbytes, the kernel waits for the arrival of several packets before
|
|
|
|
|
copying the data to the user. This guarantees a low number of system calls, i.e. lower processor usage,
|
|
|
|
|
i.e. better performance, which is a good setting for applications like sniffers. Vice versa, a small value
|
|
|
|
|
means that the kernel will copy the packets as soon as the application is ready to receive them. This is
|
|
|
|
|
suggested for real time applications (like, for example, a bridge) that need the better responsiveness from
|
2002-09-24 15:08:14 +00:00
|
|
|
|
the kernel.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\b note: this function has effect only in Windows NTx. The driver for Windows 9x doesn't offer
|
2002-09-24 15:08:14 +00:00
|
|
|
|
this possibility, therefore PacketSetMinToCopy is implemented under these systems only for compatibility.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
return DeviceIoControl(AdapterObject->hFile,pBIOCSMINTOCOPY,&nbytes,4,NULL,0,&BytesReturned,NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Sets the working mode of an adapter.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\param mode The new working mode of the adapter.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
|
|
|
|
The device driver of WinPcap has 4 working modes:
|
|
|
|
|
- Capture mode (mode = PACKET_MODE_CAPT): normal capture mode. The packets transiting on the wire are copied
|
|
|
|
|
to the application when PacketReceivePacket() is called. This is the default working mode of an adapter.
|
|
|
|
|
- Statistical mode (mode = PACKET_MODE_STAT): programmable statistical mode. PacketReceivePacket() returns, at
|
2007-10-19 23:21:45 +00:00
|
|
|
|
precise intervals, statics values on the network traffic. The interval between the statistic samples is
|
|
|
|
|
by default 1 second but it can be set to any other value (with a 1 ms precision) with the
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PacketSetReadTimeout() function. The data returned by PacketReceivePacket() when the adapter is in statistical
|
|
|
|
|
mode is shown in the following figure:<p>
|
|
|
|
|
\image html stats.gif "data structure returned by statistical mode"
|
2007-10-19 23:21:45 +00:00
|
|
|
|
Two 64-bit counters are provided: the number of packets and the amount of bytes that satisfy a filter
|
|
|
|
|
previously set with PacketSetBPF(). If no filter has been set, all the packets are counted. The counters are
|
|
|
|
|
encapsulated in a bpf_hdr structure, so that they will be parsed correctly by wpcap. Statistical mode has a
|
|
|
|
|
very low impact on system performance compared to capture mode.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
- Dump mode (mode = PACKET_MODE_DUMP): the packets are dumped to disk by the driver, in libpcap format. This
|
2007-10-19 23:21:45 +00:00
|
|
|
|
method is much faster than saving the packets after having captured them. No data is returned
|
2002-09-24 15:08:14 +00:00
|
|
|
|
by PacketReceivePacket(). If the application sets a filter with PacketSetBPF(), only the packets that satisfy
|
|
|
|
|
this filter are dumped to disk.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- Statitical Dump mode (mode = PACKET_MODE_STAT_DUMP): the packets are dumped to disk by the driver, in libpcap
|
|
|
|
|
format, like in dump mode. PacketReceivePacket() returns, at precise intervals, statics values on the
|
2002-09-24 15:08:14 +00:00
|
|
|
|
network traffic and on the amount of data saved to file, in a way similar to statistical mode.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
The data returned by PacketReceivePacket() when the adapter is in statistical dump mode is shown in
|
|
|
|
|
the following figure:<p>
|
2002-09-24 15:08:14 +00:00
|
|
|
|
\image html dump.gif "data structure returned by statistical dump mode"
|
2007-10-19 23:21:45 +00:00
|
|
|
|
Three 64-bit counters are provided: the number of packets accepted, the amount of bytes accepted and the
|
|
|
|
|
effective amount of data (including headers) dumped to file. If no filter has been set, all the packets are
|
|
|
|
|
dumped to disk. The counters are encapsulated in a bpf_hdr structure, so that they will be parsed correctly
|
2002-09-24 15:08:14 +00:00
|
|
|
|
by wpcap.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
Look at the NetMeter example in the
|
2002-09-24 15:08:14 +00:00
|
|
|
|
WinPcap developer's pack to see how to use statistics mode.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
return DeviceIoControl(AdapterObject->hFile,pBIOCSMODE,&mode,4,NULL,0,&BytesReturned,NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Sets the name of the file that will receive the packet when the adapter is in dump mode.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\param name the file name, in ASCII or UNICODE.
|
|
|
|
|
\param len the length of the buffer containing the name, in bytes.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
This function defines the file name that the driver will open to store the packets on disk when
|
2002-09-24 15:08:14 +00:00
|
|
|
|
it works in dump mode. The adapter must be in dump mode, i.e. PacketSetMode() should have been
|
|
|
|
|
called previously with mode = PACKET_MODE_DUMP. otherwise this function will fail.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
If PacketSetDumpName was already invoked on the adapter pointed by AdapterObject, the driver
|
2002-09-24 15:08:14 +00:00
|
|
|
|
closes the old file and opens the new one.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
WCHAR *FileName;
|
|
|
|
|
BOOLEAN res;
|
|
|
|
|
WCHAR NameWithPath[1024];
|
|
|
|
|
int TStrLen;
|
|
|
|
|
WCHAR *NamePos;
|
|
|
|
|
|
|
|
|
|
if(((PUCHAR)name)[1]!=0 && len>1){ //ASCII
|
|
|
|
|
FileName=SChar2WChar(name);
|
|
|
|
|
len*=2;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
else { //Unicode
|
|
|
|
|
FileName=name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TStrLen=GetFullPathName(FileName,1024,NameWithPath,&NamePos);
|
|
|
|
|
|
|
|
|
|
len=TStrLen*2+2; //add the terminating null character
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
// Try to catch malformed strings
|
|
|
|
|
if(len>2048){
|
|
|
|
|
if(((PUCHAR)name)[1]!=0 && len>1) free(FileName);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = DeviceIoControl(AdapterObject->hFile,pBIOCSETDUMPFILENAME,NameWithPath,len,NULL,0,&BytesReturned,NULL);
|
|
|
|
|
free(FileName);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\brief Set the dump mode limits.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\param maxfilesize The maximum dimension of the dump file, in bytes. 0 means no limit.
|
|
|
|
|
\param maxnpacks The maximum number of packets contained in the dump file. 0 means no limit.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
|
|
|
|
This function sets the limits after which the NPF driver stops to save the packets to file when an adapter
|
|
|
|
|
is in dump mode. This allows to limit the dump file to a precise number of bytes or packets, avoiding that
|
|
|
|
|
very long dumps fill the disk space. If both maxfilesize and maxnpacks are set, the dump is stopped when
|
|
|
|
|
the first of the two is reached.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\note When a limit is reached, the dump is stopped, but the file remains opened. In order to flush
|
2002-09-24 15:08:14 +00:00
|
|
|
|
correctly the data and access the file consistently, you need to close the adapter with PacketCloseAdapter().
|
|
|
|
|
*/
|
|
|
|
|
BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
UINT valbuff[2];
|
|
|
|
|
|
|
|
|
|
valbuff[0] = maxfilesize;
|
|
|
|
|
valbuff[1] = maxnpacks;
|
|
|
|
|
|
|
|
|
|
return DeviceIoControl(AdapterObject->hFile,
|
|
|
|
|
pBIOCSETDUMPLIMITS,
|
|
|
|
|
valbuff,
|
|
|
|
|
sizeof valbuff,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
&BytesReturned,
|
2007-10-19 23:21:45 +00:00
|
|
|
|
NULL);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\brief Returns the status of the kernel dump process, i.e. tells if one of the limits defined with PacketSetDumpLimits() was reached.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\param sync if TRUE, the function blocks until the dump is finished, otherwise it returns immediately.
|
|
|
|
|
\return TRUE if the dump is ended, FALSE otherwise.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
PacketIsDumpEnded() informs the user about the limits that were set with a previous call to
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PacketSetDumpLimits().
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\warning If no calls to PacketSetDumpLimits() were performed or if the dump process has no limits
|
2002-09-24 15:08:14 +00:00
|
|
|
|
(i.e. if the arguments of the last call to PacketSetDumpLimits() were both 0), setting sync to TRUE will
|
|
|
|
|
block the application on this call forever.
|
|
|
|
|
*/
|
|
|
|
|
BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
int IsDumpEnded;
|
|
|
|
|
BOOLEAN res;
|
|
|
|
|
|
|
|
|
|
if(sync)
|
|
|
|
|
WaitForSingleObject(AdapterObject->ReadEvent, INFINITE);
|
|
|
|
|
|
|
|
|
|
res = DeviceIoControl(AdapterObject->hFile,
|
|
|
|
|
pBIOCISDUMPENDED,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
&IsDumpEnded,
|
|
|
|
|
4,
|
|
|
|
|
&BytesReturned,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
if(res == FALSE) return TRUE; // If the IOCTL returns an error we consider the dump finished
|
|
|
|
|
|
|
|
|
|
return (BOOLEAN)IsDumpEnded;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\brief Returns the notification event associated with the read calls on an adapter.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\return The handle of the event that the driver signals when some data is available in the kernel buffer.
|
|
|
|
|
|
|
|
|
|
The event returned by this function is signaled by the driver if:
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- The adapter pointed by AdapterObject is in capture mode and an amount of data greater or equal
|
2002-09-24 15:08:14 +00:00
|
|
|
|
than the one set with the PacketSetMinToCopy() function is received from the network.
|
|
|
|
|
- the adapter pointed by AdapterObject is in capture mode, no data has been received from the network
|
|
|
|
|
but the the timeout set with the PacketSetReadTimeout() function has elapsed.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- the adapter pointed by AdapterObject is in statics mode and the the timeout set with the
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PacketSetReadTimeout() function has elapsed. This means that a new statistic sample is available.
|
|
|
|
|
|
|
|
|
|
In every case, a call to PacketReceivePacket() will return immediately.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
The event can be passed to standard Win32 functions (like WaitForSingleObject or WaitForMultipleObjects)
|
|
|
|
|
to wait until the driver's buffer contains some data. It is particularly useful in GUI applications that
|
2002-09-24 15:08:14 +00:00
|
|
|
|
need to wait concurrently on several events.
|
|
|
|
|
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
HANDLE PacketGetReadEvent(LPADAPTER AdapterObject)
|
|
|
|
|
{
|
|
|
|
|
return AdapterObject->ReadEvent;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Sets the number of times a single packet written with PacketSendPacket() will be repeated on the network.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\param nwrites Number of copies of a packet that will be physically sent by the interface.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
See PacketSendPacket() for details.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
return DeviceIoControl(AdapterObject->hFile,pBIOCSWRITEREP,&nwrites,4,NULL,0,&BytesReturned,NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Sets the timeout after which a read on an adapter returns.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param timeout indicates the timeout, in milliseconds, after which a call to PacketReceivePacket() on
|
|
|
|
|
the adapter pointed by AdapterObject will be released, also if no packets have been captured by the driver.
|
|
|
|
|
Setting timeout to 0 means no timeout, i.e. PacketReceivePacket() never returns if no packet arrives.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
A timeout of -1 causes PacketReceivePacket() to always return immediately.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\note This function works also if the adapter is working in statistics mode, and can be used to set the
|
2002-09-24 15:08:14 +00:00
|
|
|
|
time interval between two statistic reports.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
int DriverTimeOut=-1;
|
|
|
|
|
|
|
|
|
|
AdapterObject->ReadTimeOut=timeout;
|
|
|
|
|
|
|
|
|
|
return DeviceIoControl(AdapterObject->hFile,pBIOCSRTIMEOUT,&DriverTimeOut,4,NULL,0,&BytesReturned,NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Sets the size of the kernel-level buffer associated with a capture.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\param dim New size of the buffer, in \b kilobytes.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\return The function returns TRUE if successfully completed, FALSE if there is not enough memory to
|
2002-09-24 15:08:14 +00:00
|
|
|
|
allocate the new buffer.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
When a new dimension is set, the data in the old buffer is discarded and the packets stored in it are
|
|
|
|
|
lost.
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Note: the dimension of the kernel buffer affects heavily the performances of the capture process.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
An adequate buffer in the driver is able to keep the packets while the application is busy, compensating
|
|
|
|
|
the delays of the application and avoiding the loss of packets during bursts or high network activity.
|
|
|
|
|
The buffer size is set to 0 when an instance of the driver is opened: the programmer should remember to
|
2002-09-24 15:08:14 +00:00
|
|
|
|
set it to a proper value. As an example, wpcap sets the buffer size to 1MB at the beginning of a capture.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
return DeviceIoControl(AdapterObject->hFile,pBIOCSETBUFFERSIZE,&dim,4,NULL,0,&BytesReturned,NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Sets a kernel-level packet filter.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\param fp Pointer to a filtering program that will be associated with this capture or monitoring
|
2002-09-24 15:08:14 +00:00
|
|
|
|
instance and that will be executed on every incoming packet.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\return This function returns TRUE if the filter is set successfully, FALSE if an error occurs
|
|
|
|
|
or if the filter program is not accepted after a safeness check by the driver. The driver performs
|
2002-09-24 15:08:14 +00:00
|
|
|
|
the check in order to avoid system crashes due to buggy or malicious filters, and it rejects non
|
|
|
|
|
conformat filters.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
This function associates a new BPF filter to the adapter AdapterObject. The filter, pointed by fp, is a
|
2002-09-24 15:08:14 +00:00
|
|
|
|
set of bpf_insn instructions.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
A filter can be automatically created by using the pcap_compile() function of wpcap. This function
|
|
|
|
|
converts a human readable text expression with the syntax of WinDump (see the manual of WinDump at
|
|
|
|
|
http://netgroup.polito.it/windump for details) into a BPF program. If your program doesn't link wpcap, but
|
|
|
|
|
you need to know the code of a particular filter, you can launch WinDump with the -d or -dd or -ddd
|
2002-09-24 15:08:14 +00:00
|
|
|
|
flags to obtain the pseudocode.
|
|
|
|
|
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp)
|
|
|
|
|
{
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
return DeviceIoControl(AdapterObject->hFile,pBIOCSETF,(char*)fp->bf_insns,fp->bf_len*sizeof(struct bpf_insn),NULL,0,&BytesReturned,NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Returns a couple of statistic values about the current capture session.
|
|
|
|
|
\param AdapterObject Pointer to an _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 nonzero.
|
|
|
|
|
|
|
|
|
|
With this function, the programmer can know the value of two internal variables of the driver:
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- the number of packets that have been received by the adapter AdapterObject, starting at the
|
|
|
|
|
time in which it was opened with PacketOpenAdapter.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
- the number of packets that have been dropped by the driver. A packet is dropped when the kernel
|
2007-10-19 23:21:45 +00:00
|
|
|
|
buffer associated with the adapter is full.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s)
|
|
|
|
|
{
|
2002-09-24 15:08:14 +00:00
|
|
|
|
BOOLEAN Res;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
DWORD BytesReturned;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
|
|
|
|
|
|
|
|
|
|
Res = DeviceIoControl(AdapterObject->hFile,
|
|
|
|
|
pBIOCGSTATS,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
&tmpstat,
|
|
|
|
|
sizeof(struct bpf_stat),
|
|
|
|
|
&BytesReturned,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
// Copy only the first two values retrieved from the driver
|
|
|
|
|
s->bs_recv = tmpstat.bs_recv;
|
|
|
|
|
s->bs_drop = tmpstat.bs_drop;
|
|
|
|
|
|
|
|
|
|
return Res;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Returns statistic values about the current capture session. Enhanced version of PacketGetStats().
|
|
|
|
|
\param AdapterObject Pointer to an _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 nonzero.
|
|
|
|
|
|
|
|
|
|
With this function, the programmer can retireve the sname values provided by PacketGetStats(), plus:
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- the number of drops by interface (not yet supported, always 0).
|
2002-09-24 15:08:14 +00:00
|
|
|
|
- the number of packets that reached the application, i.e that were accepted by the kernel filter and
|
2007-10-19 23:21:45 +00:00
|
|
|
|
that fitted in the kernel buffer.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*/
|
|
|
|
|
BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s)
|
|
|
|
|
{
|
|
|
|
|
BOOLEAN Res;
|
|
|
|
|
DWORD BytesReturned;
|
|
|
|
|
struct bpf_stat tmpstat; // We use a support structure to avoid kernel-level inconsistencies with old or malicious applications
|
|
|
|
|
|
|
|
|
|
Res = DeviceIoControl(AdapterObject->hFile,
|
|
|
|
|
pBIOCGSTATS,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
&tmpstat,
|
|
|
|
|
sizeof(struct bpf_stat),
|
|
|
|
|
&BytesReturned,
|
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
|
|
s->bs_recv = tmpstat.bs_recv;
|
|
|
|
|
s->bs_drop = tmpstat.bs_drop;
|
|
|
|
|
s->ps_ifdrop = tmpstat.ps_ifdrop;
|
|
|
|
|
s->bs_capt = tmpstat.bs_capt;
|
|
|
|
|
|
|
|
|
|
return Res;
|
|
|
|
|
}
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Performs a query/set operation on an internal variable of the network card driver.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\param Set Determines if the operation is a set (Set=TRUE) or a query (Set=FALSE).
|
|
|
|
|
\param OidData A pointer to a _PACKET_OID_DATA structure that contains or receives the data.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\note not all the network adapters implement all the query/set functions. There is a set of mandatory
|
|
|
|
|
OID functions that is granted to be present on all the adapters, and a set of facultative functions, not
|
|
|
|
|
provided by all the cards (see the Microsoft DDKs to see which functions are mandatory). If you use a
|
2002-09-24 15:08:14 +00:00
|
|
|
|
facultative function, be careful to enclose it in an if statement to check the result.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData)
|
|
|
|
|
{
|
2003-11-14 17:13:36 +00:00
|
|
|
|
//DWORD BytesReturned;
|
2004-07-03 17:40:27 +00:00
|
|
|
|
BOOLEAN Result = 0;
|
2003-11-14 17:13:36 +00:00
|
|
|
|
/*commented out since its broken & needs fixing*/
|
|
|
|
|
/*Result=DeviceIoControl(AdapterObject->hFile,(DWORD) Set ? pBIOCSETOID : pBIOCQUERYOID,
|
2002-06-19 15:50:29 +00:00
|
|
|
|
OidData,sizeof(PACKET_OID_DATA)-1+OidData->Length,OidData,
|
2003-11-14 17:13:36 +00:00
|
|
|
|
sizeof(PACKET_OID_DATA)-1+OidData->Length,&BytesReturned,NULL);*/
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// output some debug info
|
|
|
|
|
ODSEx("PacketRequest, OID=%d ", OidData->Oid);
|
|
|
|
|
ODSEx("Length=%d ", OidData->Length);
|
|
|
|
|
ODSEx("Set=%d ", Set);
|
|
|
|
|
ODSEx("Res=%d\n", Result);
|
|
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Sets a hardware filter on the incoming packets.
|
|
|
|
|
\param AdapterObject Pointer to an _ADAPTER structure.
|
|
|
|
|
\param Filter The identifier of the filter.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
|
|
|
|
The filter defined with this filter is evaluated by the network card, at a level that is under the NPF
|
|
|
|
|
device driver. Here is a list of the most useful hardware filters (A complete list can be found in ntddndis.h):
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- NDIS_PACKET_TYPE_PROMISCUOUS: sets promiscuous mode. Every incoming packet is accepted by the adapter.
|
|
|
|
|
- NDIS_PACKET_TYPE_DIRECTED: only packets directed to the workstation's adapter are accepted.
|
|
|
|
|
- NDIS_PACKET_TYPE_BROADCAST: only broadcast packets are accepted.
|
|
|
|
|
- NDIS_PACKET_TYPE_MULTICAST: only multicast packets belonging to groups of which this adapter is a member are accepted.
|
|
|
|
|
- NDIS_PACKET_TYPE_ALL_MULTICAST: every multicast packet is accepted.
|
|
|
|
|
- NDIS_PACKET_TYPE_ALL_LOCAL: all local packets, i.e. NDIS_PACKET_TYPE_DIRECTED + NDIS_PACKET_TYPE_BROADCAST + NDIS_PACKET_TYPE_MULTICAST
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter)
|
|
|
|
|
{
|
|
|
|
|
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("PacketSetHwFilter: GlobalAlloc Failed\n");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
OidData->Oid=OID_GEN_CURRENT_PACKET_FILTER;
|
|
|
|
|
OidData->Length=sizeof(ULONG);
|
|
|
|
|
*((PULONG)OidData->Data)=Filter;
|
|
|
|
|
Status=PacketRequest(AdapterObject,TRUE,OidData);
|
|
|
|
|
GlobalFreePtr(OidData);
|
|
|
|
|
return Status;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Retrieve the list of available network adapters and their description.
|
|
|
|
|
\param pStr User allocated string that will be filled with the names of the adapters.
|
|
|
|
|
\param BufferSize Length of the buffer pointed by pStr.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
|
|
|
|
Usually, this is the first function that should be used to communicate with the driver.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
It returns the names of the adapters installed on the system <B>and supported by WinPcap</B>.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
After the names of the adapters, pStr contains a string that describes each of them.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\b Warning:
|
|
|
|
|
the result of this function is obtained querying the registry, therefore the format
|
2002-09-24 15:08:14 +00:00
|
|
|
|
of the result in Windows NTx is different from the one in Windows 9x. Windows 9x uses the ASCII
|
2007-10-19 23:21:45 +00:00
|
|
|
|
encoding method to store a string, while Windows NTx uses UNICODE. After a call to PacketGetAdapterNames
|
2002-09-24 15:08:14 +00:00
|
|
|
|
in Windows 95x, pStr contains, in succession:
|
|
|
|
|
- a variable number of ASCII strings, each with the names of an adapter, separated by a "\0"
|
|
|
|
|
- a double "\0"
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- a number of ASCII strings, each with the description of an adapter, separated by a "\0". The number
|
2002-09-24 15:08:14 +00:00
|
|
|
|
of descriptions is the same of the one of names. The fisrt description corresponds to the first name, and
|
|
|
|
|
so on.
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- a double "\0".
|
2002-09-24 15:08:14 +00:00
|
|
|
|
|
|
|
|
|
In Windows NTx, pStr contains: the names of the adapters, in UNICODE format, separated by a single UNICODE "\0" (i.e. 2 ASCII "\0"), a double UNICODE "\0", followed by the descriptions of the adapters, in ASCII format, separated by a single ASCII "\0" . The string is terminated by a double ASCII "\0".
|
|
|
|
|
- a variable number of UNICODE strings, each with the names of an adapter, separated by a UNICODE "\0"
|
|
|
|
|
- a double UNICODE "\0"
|
|
|
|
|
- a number of ASCII strings, each with the description of an adapter, separated by an ASCII "\0".
|
2007-10-19 23:21:45 +00:00
|
|
|
|
- a double ASCII "\0".
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
BOOLEAN PacketGetAdapterNames(PTSTR pStr, PULONG BufferSize)
|
2002-06-19 15:50:29 +00:00
|
|
|
|
{
|
2002-09-24 15:08:14 +00:00
|
|
|
|
HKEY LinkageKey, AdapKey;
|
|
|
|
|
DWORD RegKeySize = 0;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
LONG Status;
|
|
|
|
|
ULONG Result;
|
|
|
|
|
PTSTR BpStr;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
char *TTpStr;
|
|
|
|
|
char *DpStr;
|
|
|
|
|
char *DescBuf;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
LPADAPTER adapter;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
PPACKET_OID_DATA OidData;
|
|
|
|
|
int i = 0, k, rewind;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
DWORD dim;
|
|
|
|
|
TCHAR AdapName[256];
|
|
|
|
|
|
|
|
|
|
ODSEx("PacketGetAdapterNames: BufferSize=%d\n",*BufferSize);
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
OidData = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 512);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (OidData == NULL) {
|
|
|
|
|
ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
|
|
|
TEXT("SYSTEM\\ControlSet001\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}"),
|
|
|
|
|
0, KEY_READ, &AdapKey);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
// Get the size to allocate for the original device names
|
2002-09-24 15:08:14 +00:00
|
|
|
|
while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
|
|
|
|
|
Status = RegOpenKeyEx(AdapKey, AdapName,0, KEY_READ, &LinkageKey);
|
|
|
|
|
Status = RegOpenKeyExW(LinkageKey, L"Linkage",0, KEY_READ, &LinkageKey);
|
|
|
|
|
Status = RegQueryValueExW(LinkageKey, L"Export", NULL, NULL, NULL, &dim);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
i++;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (Status!=ERROR_SUCCESS) continue;
|
|
|
|
|
RegKeySize += dim;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Allocate the memory for the original device names
|
|
|
|
|
ODSEx("Need %d bytes for the names\n", RegKeySize+2);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize+2);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (BpStr == NULL || RegKeySize > *BufferSize) {
|
|
|
|
|
ODS("PacketGetAdapterNames: GlobalAlloc Failed\n");
|
|
|
|
|
GlobalFreePtr(OidData);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
k = 0;
|
|
|
|
|
i = 0;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
ODS("PacketGetAdapterNames: Cycling through the adapters:\n");
|
|
|
|
|
|
|
|
|
|
// Copy the names to the buffer
|
2002-09-24 15:08:14 +00:00
|
|
|
|
while ((Result = RegEnumKey(AdapKey, i, AdapName, sizeof(AdapName)/2)) == ERROR_SUCCESS) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
WCHAR UpperBindStr[64];
|
|
|
|
|
|
|
|
|
|
i++;
|
|
|
|
|
ODSEx(" %d) ", i);
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Status = RegOpenKeyEx(AdapKey,AdapName,0,KEY_READ,&LinkageKey);
|
|
|
|
|
Status = RegOpenKeyExW(LinkageKey,L"Linkage",0,KEY_READ,&LinkageKey);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
dim=sizeof(UpperBindStr);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Status=RegQueryValueExW(LinkageKey,L"UpperBind",NULL,NULL,(PUCHAR)UpperBindStr,&dim);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODSEx("UpperBind=%S ", UpperBindStr);
|
|
|
|
|
|
|
|
|
|
if( Status!=ERROR_SUCCESS || _wcsicmp(UpperBindStr,L"NdisWan")==0 ){
|
|
|
|
|
ODS("Name = SKIPPED\n");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dim=RegKeySize-k;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Status=RegQueryValueExW(LinkageKey,L"Export",NULL,NULL,(LPBYTE)BpStr+k,&dim);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if(Status!=ERROR_SUCCESS){
|
|
|
|
|
ODS("Name = SKIPPED (error reading the key)\n");
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ODSEx("Name = %S\n", (LPBYTE)BpStr+k);
|
|
|
|
|
|
|
|
|
|
k+=dim-2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CloseHandle(AdapKey);
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG_TO_FILE
|
|
|
|
|
//dump BpStr for debug purposes
|
|
|
|
|
ODS("Dumping BpStr:");
|
|
|
|
|
{
|
|
|
|
|
FILE *f;
|
|
|
|
|
f = fopen("winpcap_debug.txt", "a");
|
|
|
|
|
for(i=0;i<k;i++){
|
|
|
|
|
if(!(i%32))fprintf(f, "\n ");
|
|
|
|
|
fprintf(f, "%c " , *((LPBYTE)BpStr+i));
|
|
|
|
|
}
|
|
|
|
|
fclose(f);
|
|
|
|
|
}
|
|
|
|
|
ODS("\n");
|
|
|
|
|
#endif
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (k != 0){
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
DescBuf=GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
|
|
|
|
|
if (DescBuf == NULL) {
|
|
|
|
|
GlobalFreePtr (BpStr);
|
|
|
|
|
GlobalFreePtr(OidData);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
DpStr=DescBuf;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
for(i=0,k=0;BpStr[i]!=0 || BpStr[i+1]!=0;){
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if(k+wcslen(BpStr+i)+30 > *BufferSize){
|
|
|
|
|
// Input buffer too small
|
|
|
|
|
GlobalFreePtr(OidData);
|
|
|
|
|
GlobalFreePtr (BpStr);
|
|
|
|
|
GlobalFreePtr (DescBuf);
|
|
|
|
|
ODS("PacketGetAdapterNames: Input buffer too small!\n");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create the device name
|
|
|
|
|
rewind=k;
|
|
|
|
|
memcpy(pStr+k,BpStr+i,16);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
memcpy(pStr+k+8,TEXT("NPF_"),8);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
i+=8;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
k+=12;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
while(BpStr[i-1]!=0){
|
|
|
|
|
pStr[k++]=BpStr[i++];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Open the adapter
|
|
|
|
|
adapter=PacketOpenAdapter(pStr+rewind);
|
|
|
|
|
if(adapter==NULL){
|
|
|
|
|
k=rewind;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Retrieve the description
|
|
|
|
|
OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
|
|
|
|
|
OidData->Length = 256;
|
|
|
|
|
ZeroMemory(OidData->Data,256);
|
|
|
|
|
Status = PacketRequest(adapter,FALSE,OidData);
|
|
|
|
|
if(Status==0 || ((char*)OidData->Data)[0]==0){
|
|
|
|
|
k=rewind;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ODSEx("Adapter Description=%s\n\n",OidData->Data);
|
|
|
|
|
|
|
|
|
|
// Copy the description
|
|
|
|
|
TTpStr=(char*)(OidData->Data);
|
|
|
|
|
while(*TTpStr!=0){
|
|
|
|
|
*DpStr++=*TTpStr++;
|
|
|
|
|
}
|
|
|
|
|
*DpStr++=*TTpStr++;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Close the adapter
|
|
|
|
|
PacketCloseAdapter(adapter);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*DpStr = 0;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
pStr[k++] = 0;
|
|
|
|
|
pStr[k] = 0;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
|
|
|
|
|
memcpy(pStr + k, DescBuf, DpStr - DescBuf);
|
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
GlobalFreePtr(OidData);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
GlobalFreePtr(BpStr);
|
|
|
|
|
GlobalFreePtr(DescBuf);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("\nPacketGetAdapterNames: ended with failure\n");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GlobalFreePtr(OidData);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
GlobalFreePtr(BpStr);
|
|
|
|
|
GlobalFreePtr(DescBuf);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
ODS("\nPacketGetAdapterNames: ended correctly\n");
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else{
|
2002-09-24 15:08:14 +00:00
|
|
|
|
DWORD RegType;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
ODS("Adapters not found under SYSTEM\\ControlSet001\\Control\\Class. Using the TCP/IP bindings.\n");
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
GlobalFreePtr(BpStr);
|
|
|
|
|
Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
|
|
|
TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage"),
|
|
|
|
|
0, KEY_READ, &LinkageKey);
|
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Retrieve the length of the key
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, NULL, &RegKeySize);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Allocate the buffer
|
2002-09-24 15:08:14 +00:00
|
|
|
|
BpStr = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, RegKeySize + 2);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (BpStr == NULL || RegKeySize > *BufferSize) {
|
|
|
|
|
GlobalFreePtr(OidData);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Status = RegQueryValueEx(LinkageKey, TEXT("bind"), NULL, &RegType, (LPBYTE)BpStr, &RegKeySize);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
RegCloseKey(LinkageKey);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
|
|
|
|
//ODS("SYSTEM\\ControlSet001\\Control\\Class - RegKey not found.\n");
|
|
|
|
|
ODS("SYSTEM\\ControlSet001\\Services\\Tcpip\\Linkage - RegKey not found.\n");
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (Status == ERROR_SUCCESS) {
|
|
|
|
|
DescBuf = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (DescBuf == NULL) {
|
2002-09-24 15:08:14 +00:00
|
|
|
|
GlobalFreePtr(BpStr);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
GlobalFreePtr(OidData);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
DpStr = DescBuf;
|
|
|
|
|
for (i = 0, k = 0; BpStr[i] != 0 || BpStr[i+1] != 0; ) {
|
|
|
|
|
if (k + wcslen(BpStr + i) + 30 > *BufferSize) {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Input buffer too small
|
|
|
|
|
GlobalFreePtr(OidData);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
GlobalFreePtr(BpStr);
|
|
|
|
|
GlobalFreePtr(DescBuf);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
|
|
|
|
|
ODS("\tCreating a device name - started.\n");
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Create the device name
|
2002-09-24 15:08:14 +00:00
|
|
|
|
rewind = k;
|
|
|
|
|
memcpy(pStr + k,BpStr + i,16);
|
|
|
|
|
memcpy(pStr + k + 8, TEXT("NPF_"), 8);
|
|
|
|
|
i += 8;
|
|
|
|
|
k += 12;
|
|
|
|
|
while (BpStr[i - 1] != 0) {
|
|
|
|
|
pStr[k++] = BpStr[i++];
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
// Open the adapter
|
2002-09-24 15:08:14 +00:00
|
|
|
|
adapter = PacketOpenAdapter(pStr+rewind);
|
|
|
|
|
if (adapter == NULL) {
|
|
|
|
|
k = rewind;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// Retrieve the description
|
|
|
|
|
OidData->Oid = OID_GEN_VENDOR_DESCRIPTION;
|
|
|
|
|
OidData->Length = 256;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
Status = PacketRequest(adapter, FALSE, OidData);
|
|
|
|
|
if (Status == 0 || ((char*)OidData->Data)[0] == 0) {
|
|
|
|
|
k = rewind;
|
|
|
|
|
ODS("\tCreating a device name - Retrieve the description.\n");
|
2002-06-19 15:50:29 +00:00
|
|
|
|
continue;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Copy the description
|
2002-09-24 15:08:14 +00:00
|
|
|
|
TTpStr = (char*)(OidData->Data);
|
|
|
|
|
while (*TTpStr != 0){
|
|
|
|
|
*DpStr++ = *TTpStr++;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*DpStr++ = *TTpStr++;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Close the adapter
|
|
|
|
|
PacketCloseAdapter(adapter);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
|
|
|
|
|
ODS("\tCreating a device name - completed.\n");
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*DpStr = 0;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
pStr[k++] = 0;
|
|
|
|
|
pStr[k] = 0;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if ((ULONG)(DpStr - DescBuf + k) < *BufferSize) {
|
|
|
|
|
memcpy(pStr + k, DescBuf, DpStr-DescBuf);
|
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
GlobalFreePtr(OidData);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
GlobalFreePtr(BpStr);
|
|
|
|
|
GlobalFreePtr(DescBuf);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
GlobalFreePtr(OidData);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
GlobalFreePtr(BpStr);
|
|
|
|
|
GlobalFreePtr(DescBuf);
|
|
|
|
|
ODS("PacketGetAdapterNames() returning TRUE\n");
|
2002-06-19 15:50:29 +00:00
|
|
|
|
return TRUE;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
} else {
|
2002-06-19 15:50:29 +00:00
|
|
|
|
MessageBox(NULL,TEXT("Can not find TCP/IP bindings.\nIn order to run the packet capture driver you must install TCP/IP."),szWindowTitle,MB_OK);
|
2002-09-24 15:08:14 +00:00
|
|
|
|
ODS("Cannot find the TCP/IP bindings\n");
|
2002-06-19 15:50:29 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Returns comprehensive information the addresses of an adapter.
|
|
|
|
|
\param AdapterName String that contain _ADAPTER structure.
|
|
|
|
|
\param buffer A user allocated array of npf_if_addr that will be filled by the function.
|
|
|
|
|
\param NEntries Size of the array (in npf_if_addr).
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
This function grabs from the registry information like the IP addresses, the netmasks
|
|
|
|
|
and the broadcast addresses of an interface. The buffer passed by the user is filled with
|
2002-09-24 15:08:14 +00:00
|
|
|
|
npf_if_addr structures, each of which contains the data for a single address. If the buffer
|
|
|
|
|
is full, the reaming addresses are dropeed, therefore set its dimension to sizeof(npf_if_addr)
|
|
|
|
|
if you want only the first address.
|
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
BOOLEAN PacketGetNetInfoEx(LPTSTR AdapterName, npf_if_addr* buffer, PLONG NEntries)
|
|
|
|
|
{
|
|
|
|
|
char *AdapterNameA;
|
|
|
|
|
WCHAR *AdapterNameU;
|
|
|
|
|
WCHAR *ifname;
|
|
|
|
|
HKEY SystemKey;
|
|
|
|
|
HKEY InterfaceKey;
|
|
|
|
|
HKEY ParametersKey;
|
|
|
|
|
HKEY TcpIpKey;
|
|
|
|
|
HKEY UnderTcpKey;
|
|
|
|
|
LONG status;
|
|
|
|
|
WCHAR String[1024+1];
|
|
|
|
|
DWORD RegType;
|
|
|
|
|
ULONG BufLen;
|
|
|
|
|
DWORD DHCPEnabled;
|
|
|
|
|
struct sockaddr_in *TmpAddr, *TmpBroad;
|
|
|
|
|
LONG naddrs,nmasks,StringPos;
|
|
|
|
|
DWORD ZeroBroadcast;
|
|
|
|
|
|
|
|
|
|
AdapterNameA = (char*)AdapterName;
|
|
|
|
|
if(AdapterNameA[1] != 0) { //ASCII
|
|
|
|
|
AdapterNameU = SChar2WChar(AdapterNameA);
|
|
|
|
|
AdapterName = AdapterNameU;
|
|
|
|
|
} else { //Unicode
|
|
|
|
|
AdapterNameU = NULL;
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
ifname = wcsrchr(AdapterName, '\\');
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (ifname == NULL)
|
|
|
|
|
ifname = AdapterName;
|
|
|
|
|
else
|
|
|
|
|
ifname++;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (wcsncmp(ifname, L"NPF_", 4) == 0)
|
|
|
|
|
ifname += 4;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
if( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
2002-09-24 15:08:14 +00:00
|
|
|
|
TEXT("SYSTEM\\ControlSet001\\Services\\Tcpip\\Parameters\\Interfaces"),
|
|
|
|
|
0, KEY_READ, &UnderTcpKey) == ERROR_SUCCESS)
|
2002-06-19 15:50:29 +00:00
|
|
|
|
{
|
2002-09-24 15:08:14 +00:00
|
|
|
|
status = RegOpenKeyExW(UnderTcpKey,ifname,0,KEY_READ,&TcpIpKey);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(UnderTcpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// Query the registry key with the interface's adresses
|
2002-09-24 15:08:14 +00:00
|
|
|
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
|
|
|
TEXT("SYSTEM\\ControlSet001\\Services"),
|
|
|
|
|
0,KEY_READ,&SystemKey);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
|
|
|
goto fail;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(SystemKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
RegCloseKey(SystemKey);
|
|
|
|
|
status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(InterfaceKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
RegCloseKey(InterfaceKey);
|
|
|
|
|
status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(ParametersKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
RegCloseKey(ParametersKey);
|
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BufLen = 4;
|
|
|
|
|
/* Try to detect if the interface has a zero broadcast addr */
|
|
|
|
|
status=RegQueryValueEx(TcpIpKey,TEXT("UseZeroBroadcast"),NULL,&RegType,(LPBYTE)&ZeroBroadcast,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
|
|
|
ZeroBroadcast=0;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = 4;
|
|
|
|
|
/* See if DHCP is used by this system */
|
|
|
|
|
status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
|
|
|
DHCPEnabled=0;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
/* Retrieve the adrresses */
|
|
|
|
|
if(DHCPEnabled){
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
// Open the key with the addresses
|
|
|
|
|
status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// scan the key to obtain the addresses
|
|
|
|
|
StringPos = 0;
|
|
|
|
|
for(naddrs = 0;naddrs <* NEntries;naddrs++){
|
|
|
|
|
TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
|
|
|
|
|
TmpAddr->sin_family = AF_INET;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
|
|
|
|
|
TmpBroad->sin_family = AF_INET;
|
|
|
|
|
if(ZeroBroadcast==0)
|
|
|
|
|
TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
|
|
|
|
|
else
|
|
|
|
|
TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
|
|
|
|
|
|
|
|
|
|
while(*(String + StringPos) != 0)StringPos++;
|
|
|
|
|
StringPos++;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
|
2007-10-19 23:21:45 +00:00
|
|
|
|
break;
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
else break;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
// Open the key with the netmasks
|
|
|
|
|
status = RegQueryValueEx(TcpIpKey,TEXT("DhcpSubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// scan the key to obtain the masks
|
|
|
|
|
StringPos = 0;
|
|
|
|
|
for(nmasks = 0;nmasks < *NEntries;nmasks++){
|
|
|
|
|
TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
|
|
|
|
|
TmpAddr->sin_family = AF_INET;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
while(*(String + StringPos) != 0)StringPos++;
|
|
|
|
|
StringPos++;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// The number of masks MUST be equal to the number of adresses
|
|
|
|
|
if(nmasks != naddrs){
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
else{
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
// Open the key with the addresses
|
|
|
|
|
status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// scan the key to obtain the addresses
|
|
|
|
|
StringPos = 0;
|
|
|
|
|
for(naddrs = 0;naddrs < *NEntries;naddrs++){
|
|
|
|
|
TmpAddr = (struct sockaddr_in *) &(buffer[naddrs].IPAddress);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
|
|
|
|
|
TmpAddr->sin_family = AF_INET;
|
|
|
|
|
|
|
|
|
|
TmpBroad = (struct sockaddr_in *) &(buffer[naddrs].Broadcast);
|
|
|
|
|
TmpBroad->sin_family = AF_INET;
|
|
|
|
|
if(ZeroBroadcast==0)
|
|
|
|
|
TmpBroad->sin_addr.S_un.S_addr = 0xffffffff; // 255.255.255.255
|
|
|
|
|
else
|
|
|
|
|
TmpBroad->sin_addr.S_un.S_addr = 0; // 0.0.0.0
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
while(*(String + StringPos) != 0)StringPos++;
|
|
|
|
|
StringPos++;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
// Open the key with the netmasks
|
|
|
|
|
status = RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,(LPBYTE)String,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// scan the key to obtain the masks
|
|
|
|
|
StringPos = 0;
|
|
|
|
|
for(nmasks = 0;nmasks <* NEntries;nmasks++){
|
|
|
|
|
TmpAddr = (struct sockaddr_in *) &(buffer[nmasks].SubnetMask);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if((TmpAddr->sin_addr.S_un.S_addr = inet_addrU(String + StringPos))!= -1){
|
|
|
|
|
TmpAddr->sin_family = AF_INET;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
while(*(String + StringPos) != 0)StringPos++;
|
|
|
|
|
StringPos++;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if(*(String + StringPos) == 0 || (StringPos * sizeof (WCHAR)) >= BufLen)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
// The number of masks MUST be equal to the number of adresses
|
|
|
|
|
if(nmasks != naddrs){
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
*NEntries = naddrs + 1;
|
|
|
|
|
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
return TRUE;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
fail:
|
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2002-09-24 15:08:14 +00:00
|
|
|
|
/*!
|
|
|
|
|
\brief Returns the IP address and the netmask of an adapter.
|
|
|
|
|
\param AdapterName String that contain _ADAPTER structure.
|
|
|
|
|
\param netp Pointer to a variable that will receive the IP address of the adapter.
|
|
|
|
|
\param maskp Pointer to a variable that will receive the netmask of the adapter.
|
|
|
|
|
\return If the function succeeds, the return value is nonzero.
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
\note this function is obsolete and is maintained for backward compatibility. Use PacketGetNetInfoEx() instead.
|
2002-09-24 15:08:14 +00:00
|
|
|
|
*/
|
2002-06-19 15:50:29 +00:00
|
|
|
|
|
|
|
|
|
BOOLEAN PacketGetNetInfo(LPTSTR AdapterName, PULONG netp, PULONG maskp)
|
|
|
|
|
{
|
|
|
|
|
char *AdapterNameA;
|
|
|
|
|
WCHAR *AdapterNameU;
|
|
|
|
|
WCHAR *ifname;
|
|
|
|
|
HKEY SystemKey;
|
|
|
|
|
HKEY InterfaceKey;
|
|
|
|
|
HKEY ParametersKey;
|
|
|
|
|
HKEY TcpIpKey;
|
|
|
|
|
LONG status;
|
|
|
|
|
WCHAR String[1024+1];
|
|
|
|
|
DWORD RegType;
|
|
|
|
|
ULONG BufLen;
|
|
|
|
|
DWORD DHCPEnabled;
|
|
|
|
|
ULONG TAddr,i;
|
|
|
|
|
|
|
|
|
|
AdapterNameA = (char*)AdapterName;
|
|
|
|
|
if(AdapterNameA[1] != 0) { //ASCII
|
|
|
|
|
AdapterNameU = SChar2WChar(AdapterNameA);
|
|
|
|
|
AdapterName = AdapterNameU;
|
|
|
|
|
} else { //Unicode
|
|
|
|
|
AdapterNameU = NULL;
|
|
|
|
|
}
|
|
|
|
|
ifname = wcsrchr(AdapterName, '\\');
|
|
|
|
|
if (ifname == NULL)
|
|
|
|
|
ifname = AdapterName;
|
|
|
|
|
else
|
|
|
|
|
ifname++;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
if (wcsncmp(ifname, L"NPF_", 4) == 0)
|
|
|
|
|
ifname += 4;
|
|
|
|
|
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
|
|
|
TEXT("SYSTEM\\ControlSet001\\Services"),
|
|
|
|
|
0,KEY_READ,&SystemKey);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
|
|
|
goto fail;
|
2002-09-24 15:08:14 +00:00
|
|
|
|
status = RegOpenKeyExW(SystemKey,ifname,0,KEY_READ,&InterfaceKey);
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(SystemKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
RegCloseKey(SystemKey);
|
|
|
|
|
status = RegOpenKeyEx(InterfaceKey,TEXT("Parameters"),0,KEY_READ,&ParametersKey);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(InterfaceKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
RegCloseKey(InterfaceKey);
|
|
|
|
|
status = RegOpenKeyEx(ParametersKey,TEXT("TcpIp"),0,KEY_READ,&TcpIpKey);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(ParametersKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
RegCloseKey(ParametersKey);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = 4;
|
|
|
|
|
/* See if DHCP is used by this system */
|
|
|
|
|
status=RegQueryValueEx(TcpIpKey,TEXT("EnableDHCP"),NULL,&RegType,(LPBYTE)&DHCPEnabled,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS)
|
|
|
|
|
DHCPEnabled=0;
|
|
|
|
|
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
/* Retrieve the netmask */
|
|
|
|
|
if(DHCPEnabled){
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
status = RegQueryValueEx(TcpIpKey,TEXT("DhcpIPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TAddr = inet_addrU(String);
|
|
|
|
|
// swap bytes for backward compatibility
|
|
|
|
|
for(i=0;i<4;i++){
|
|
|
|
|
*((char*)netp+i) = *((char*)&TAddr+3-i);
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
status=RegQueryValueEx(TcpIpKey,TEXT("DHCPSubnetMask"),NULL,&RegType,
|
|
|
|
|
(LPBYTE)String,&BufLen);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
TAddr = inet_addrU(String);
|
|
|
|
|
// swap bytes for backward compatibility
|
|
|
|
|
for(i=0;i<4;i++){
|
|
|
|
|
*((char*)maskp+i) = *((char*)&TAddr+3-i);
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
|
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
status = RegQueryValueEx(TcpIpKey,TEXT("IPAddress"),NULL,&RegType,(LPBYTE)String,&BufLen);
|
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TAddr = inet_addrU(String);
|
|
|
|
|
// swap bytes for backward compatibility
|
|
|
|
|
for(i=0;i<4;i++){
|
|
|
|
|
*((char*)netp+i) = *((char*)&TAddr+3-i);
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
BufLen = sizeof String;
|
|
|
|
|
status=RegQueryValueEx(TcpIpKey,TEXT("SubnetMask"),NULL,&RegType,
|
|
|
|
|
(LPBYTE)String,&BufLen);
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
TAddr = inet_addrU(String);
|
|
|
|
|
// swap bytes for backward compatibility
|
|
|
|
|
for(i=0;i<4;i++){
|
|
|
|
|
*((char*)maskp+i) = *((char*)&TAddr+3-i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (status != ERROR_SUCCESS) {
|
|
|
|
|
RegCloseKey(TcpIpKey);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
return TRUE;
|
2007-10-19 23:21:45 +00:00
|
|
|
|
|
2002-06-19 15:50:29 +00:00
|
|
|
|
fail:
|
|
|
|
|
if (AdapterNameU != NULL)
|
|
|
|
|
free(AdapterNameU);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
2002-09-24 15:08:14 +00:00
|
|
|
|
|
|
|
|
|
/* @} */
|