2010 lines
70 KiB
C
2010 lines
70 KiB
C
/*++ BUILD Version: 0001 // Increment this if a change has global effects
|
||
|
||
Copyright (c) 1992 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
perftcp.c
|
||
|
||
Abstract:
|
||
|
||
This file implements the Extensible Objects for
|
||
the TCP/IP LAN object types
|
||
|
||
Created:
|
||
|
||
Christos Tsollis 08/26/92
|
||
|
||
Revision History:
|
||
|
||
10/28/92 a-robw (Bob Watson)
|
||
added Message Logging and Foreign Computer Support interface.
|
||
|
||
|
||
--*/
|
||
//
|
||
// Disable SNMP interface
|
||
//
|
||
// This file has been modified to circumvent the SNMP service and
|
||
// go right to the agent DLL. In doing this, performance has been
|
||
// improved at the expense of only being able to query the local
|
||
// machine. The USE_SNMP flag has been used to save as much of the
|
||
// old code as possible (it used to work) but the emphesis of this
|
||
// modification is to make it work "around" SNMP and, as such, the
|
||
// USE_SNMP blocks of code HAVE NOT (at this time) BEEN TESTED!
|
||
// Caveat Emptor! (a-robw)
|
||
//
|
||
#ifdef USE_SNMP
|
||
#undef USE_SNMP
|
||
#endif
|
||
|
||
//#define LOAD_MGMTAPI
|
||
#ifdef LOAD_MGMTAPI
|
||
#undef LOAD_MGMTAPI
|
||
#endif
|
||
|
||
#define LOAD_INETMIB1
|
||
//#ifdef LOAD_INETMIB1
|
||
//#undef LOAD_INETMIB1
|
||
//#endif
|
||
|
||
//
|
||
// Disable DSIS interface for now
|
||
//
|
||
#ifdef USE_DSIS
|
||
#undef USE_DSIS
|
||
#endif
|
||
|
||
//
|
||
// Use IPHLPAPI.DLL
|
||
//
|
||
#ifndef USE_SNMP
|
||
#define USE_IPHLPAPI
|
||
#ifdef LOAD_INETMIB1
|
||
#undef LOAD_INETMIB1
|
||
#endif
|
||
#endif
|
||
|
||
//
|
||
// Include Files
|
||
//
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
#include <ntprfctr.h>
|
||
#include <windows.h>
|
||
#include <winperf.h>
|
||
#include <winbase.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#ifdef USE_SNMP
|
||
#include <mgmtapi.h>
|
||
#endif
|
||
#include <snmp.h>
|
||
#ifdef USE_IPHLPAPI
|
||
#include <iphlpapi.h>
|
||
#endif
|
||
#include "perfctr.h" // error message definition
|
||
#include "perfmsg.h"
|
||
#include "perfutil.h"
|
||
#include "perfnbt.h"
|
||
//#include "perfdsis.h" ! not yet !
|
||
#ifndef USE_IPHLPAPI
|
||
#include "perftcp.h"
|
||
#endif
|
||
#include "datatcp.h"
|
||
|
||
#define ALIGN_SIZE 0x00000008
|
||
|
||
//
|
||
// Global Variables
|
||
//
|
||
|
||
//
|
||
// References to constants which initialize the Object type definitions
|
||
//
|
||
|
||
extern NET_INTERFACE_DATA_DEFINITION NetInterfaceDataDefinition;
|
||
extern IP_DATA_DEFINITION IpDataDefinition;
|
||
extern ICMP_DATA_DEFINITION IcmpDataDefinition;
|
||
extern TCP_DATA_DEFINITION TcpDataDefinition;
|
||
extern UDP_DATA_DEFINITION UdpDataDefinition;
|
||
|
||
|
||
#ifndef USE_SNMP // only include if not using SNMP interface
|
||
//
|
||
HANDLE hSnmpEvent = NULL; // handler for SNMP Extension Agent
|
||
|
||
#endif
|
||
|
||
//
|
||
// TCP/IP data structures
|
||
//
|
||
#ifdef USE_SNMP
|
||
LPSNMP_MGR_SESSION TcpIpSession = (LPSNMP_MGR_SESSION) NULL;
|
||
// The SNMP manager session providing
|
||
// the requested information.
|
||
#else
|
||
BOOL TcpIpSession = FALSE;
|
||
// The SNMP manager session providing
|
||
// the requested information.
|
||
#endif
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
#define MAX_INTERFACE_LEN MAX_PATH // Maximum length of a network interface
|
||
// name
|
||
#define DEFAULT_INTERFACES 20 // Default interfaces count
|
||
|
||
DWORD IfNum;
|
||
MIB_IPSTATS IpStats;
|
||
MIB_ICMP IcmpStats;
|
||
MIB_TCPSTATS TcpStats;
|
||
MIB_UDPSTATS UdpStats;
|
||
PMIB_IFTABLE IfTable = NULL;
|
||
DWORD IfTableSize = 0;
|
||
#else
|
||
AsnObjectName RefNames[NO_OF_OIDS];
|
||
|
||
RFC1157VarBind RefVariableBindingsArray[NO_OF_OIDS],
|
||
VariableBindingsArray[NO_OF_OIDS];
|
||
// The array of the variable bindings,
|
||
// used by the SNMP agent functions
|
||
// to record the info we want for the
|
||
// IP, ICMP, TCP and UDP protocols
|
||
|
||
|
||
|
||
|
||
RFC1157VarBind IFPermVariableBindingsArray[NO_OF_IF_OIDS];
|
||
// The initialization array of the
|
||
// variable bindings,
|
||
// used by the SNMP agent functions
|
||
// to record the info we want for each
|
||
// of the Network Interfaces
|
||
|
||
|
||
RFC1157VarBindList RefVariableBindings;
|
||
RFC1157VarBindList RefIFVariableBindings;
|
||
RFC1157VarBindList RefVariableBindingsICMP;
|
||
// The headers of the lists with the
|
||
// variable bindings.
|
||
// The headers of the lists with the
|
||
// variable bindings.
|
||
|
||
RFC1157VarBind NetIfRequest; // structure for net request
|
||
RFC1157VarBindList NetIfRequestList;
|
||
|
||
//
|
||
// Constants
|
||
//
|
||
|
||
#define TIMEOUT 500 // Communication timeout in milliseconds
|
||
#define RETRIES 5 // Communication time-out/retry count
|
||
|
||
#define MAX_INTERFACE_LEN 10 // Maximum length of a network interface
|
||
// name
|
||
|
||
|
||
#define OIDS_OFFSET 0 // Offset of other than the ICMP Oids
|
||
// in the VariableBindingsArray[]
|
||
#define ICMP_OIDS_OFFSET 29 // Offset of the ICMP Oids in the array
|
||
|
||
|
||
|
||
#define OIDS_LENGTH 29 // Number of the other than the ICMP
|
||
// Oids in the VariableBindingsArray[]
|
||
#define ICMP_OIDS_LENGTH 26 // Number of the ICMP Oids in the array
|
||
|
||
//
|
||
// Macro Definitions (To avoid long expressions)
|
||
//
|
||
|
||
#define IF_COUNTER(INDEX) \
|
||
(IFVariableBindings.list[(INDEX)].value.asnValue.counter)
|
||
#define IF_GAUGE(INDEX) \
|
||
(IFVariableBindings.list[(INDEX)].value.asnValue.gauge)
|
||
#define IP_COUNTER(INDEX) \
|
||
(VariableBindings.list[(INDEX)].value.asnValue.counter)
|
||
#define ICMP_COUNTER(INDEX) \
|
||
(VariableBindingsICMP.list[(INDEX)].value.asnValue.counter)
|
||
#define TCP_COUNTER(INDEX) \
|
||
(VariableBindings.list[(INDEX)].value.asnValue.counter)
|
||
#define UDP_COUNTER(INDEX) \
|
||
(VariableBindings.list[(INDEX)].value.asnValue.counter)
|
||
#define TCP_GAUGE(INDEX) \
|
||
(VariableBindings.list[(INDEX)].value.asnValue.gauge)
|
||
#endif
|
||
|
||
#define TCP_OBJECT 0x00000001
|
||
#define UDP_OBJECT 0x00000002
|
||
#define IP_OBJECT 0x00000004
|
||
#define ICMP_OBJECT 0x00000008
|
||
#define NET_OBJECT 0x00000010
|
||
#define NBT_OBJECT 0x00000020
|
||
#define SNMP_OBJECTS (TCP_OBJECT+UDP_OBJECT+IP_OBJECT+ICMP_OBJECT+NET_OBJECT)
|
||
#define SNMP_ERROR 0x40000000
|
||
|
||
|
||
#define DO_COUNTER_OBJECT(flags,counter) \
|
||
((((flags) & (counter)) == (counter)) ? TRUE : FALSE)
|
||
|
||
//
|
||
// Function Prototypes
|
||
//
|
||
|
||
PM_OPEN_PROC OpenTcpIpPerformanceData;
|
||
PM_COLLECT_PROC CollectTcpIpPerformanceData;
|
||
PM_CLOSE_PROC CloseTcpIpPerformanceData;
|
||
|
||
#ifdef LOAD_INETMIB1
|
||
HANDLE hInetMibDll;
|
||
PFNSNMPEXTENSIONINIT pSnmpExtensionInit;
|
||
PFNSNMPEXTENSIONQUERY pSnmpExtensionQuery;
|
||
#endif
|
||
|
||
DWORD dwTcpRefCount = 0;
|
||
|
||
static const WCHAR szFriendlyNetworkInterfaceNames[] = {L"FriendlyNetworkInterfaceNames"};
|
||
static const WCHAR szTcpipPerformancePath[] = {L"SYSTEM\\CurrentControlSet\\Services\\TcpIp\\Performance"};
|
||
static BOOL bUseFriendlyNames = FALSE;
|
||
|
||
__inline Assign64(
|
||
IN LONGLONG qwSrc,
|
||
IN PLARGE_INTEGER pqwDest
|
||
)
|
||
{
|
||
PLARGE_INTEGER pqwSrc = (PLARGE_INTEGER) &qwSrc;
|
||
pqwDest->LowPart = pqwSrc->LowPart;
|
||
pqwDest->HighPart = pqwSrc->HighPart;
|
||
}
|
||
|
||
static
|
||
BOOL
|
||
FriendlyNameIsSet ()
|
||
{
|
||
BOOL bReturn = TRUE;
|
||
|
||
DWORD dwStatus = ERROR_SUCCESS;
|
||
HKEY hKeyTcpipPerformance = NULL;
|
||
DWORD dwType = 0;
|
||
DWORD dwSize = 0;
|
||
DWORD dwValue = 0;
|
||
|
||
dwStatus = RegOpenKeyExW (
|
||
HKEY_LOCAL_MACHINE,
|
||
szTcpipPerformancePath,
|
||
0L,
|
||
KEY_READ,
|
||
&hKeyTcpipPerformance);
|
||
|
||
if (dwStatus == ERROR_SUCCESS) {
|
||
dwSize = sizeof(dwValue);
|
||
dwStatus = RegQueryValueExW (
|
||
hKeyTcpipPerformance,
|
||
szFriendlyNetworkInterfaceNames,
|
||
NULL,
|
||
&dwType,
|
||
(LPBYTE)&dwValue,
|
||
&dwSize);
|
||
|
||
if ((dwStatus == ERROR_SUCCESS) && (dwValue == 0) &&
|
||
((dwType == REG_DWORD) || ((dwType == REG_BINARY) && (dwSize == sizeof (DWORD))))) {
|
||
bReturn = FALSE;
|
||
}
|
||
|
||
RegCloseKey (hKeyTcpipPerformance);
|
||
}
|
||
|
||
return bReturn;
|
||
}
|
||
|
||
DWORD
|
||
OpenTcpIpPerformanceData (
|
||
IN LPWSTR dwVoid // Argument needed only to conform to calling
|
||
// interface for this routine. (NT > 312) RBW
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will open all the TCP/IP devices and remember the handles
|
||
returned by the devices.
|
||
|
||
|
||
Arguments:
|
||
|
||
IN LPWSTR dwVoid
|
||
not used
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful completion
|
||
error returned by OpenNbtPerformanceData
|
||
error returned by OpenDsisPerformanceData
|
||
or Win32 Error value
|
||
|
||
--*/
|
||
{
|
||
DWORD Status;
|
||
TCHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1];
|
||
DWORD cchBuffer = MAX_COMPUTERNAME_LENGTH+1;
|
||
|
||
DWORD dwDataReturn[2]; // event log data
|
||
#ifdef LOAD_INETMIB1
|
||
UINT nErrorMode;
|
||
#endif
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
register i;
|
||
#ifdef LOAD_MGMTAPI
|
||
HANDLE hMgmtApiDll; // handle to library
|
||
FARPROC SnmpMgrStrToOid; // address of function
|
||
#else
|
||
#define SnmpMgrStrToOid(a,b) SnmpMgrText2Oid((a),(b))
|
||
#endif
|
||
|
||
#ifdef LOAD_INETMIB1
|
||
AsnObjectIdentifier SnmpOid;
|
||
#endif
|
||
#endif
|
||
|
||
UNREFERENCED_PARAMETER (dwVoid);
|
||
|
||
MonOpenEventLog ();
|
||
|
||
REPORT_INFORMATION (TCP_OPEN_ENTERED, LOG_VERBOSE);
|
||
|
||
HEAP_PROBE();
|
||
|
||
if (dwTcpRefCount == 0) {
|
||
// Open NBT
|
||
Status = OpenNbtPerformanceData (0L);
|
||
if ( Status != ERROR_SUCCESS ) {
|
||
// NBT reports any Open errors to the user
|
||
REPORT_ERROR (TCP_NBT_OPEN_FAIL, LOG_DEBUG);
|
||
return Status;
|
||
}
|
||
REPORT_INFORMATION (TCP_NBT_OPEN_SUCCESS, LOG_VERBOSE);
|
||
|
||
#ifdef USE_DSIS
|
||
Status = OpenDsisPerformanceData (0L);
|
||
if (Status != ERROR_SUCCESS) {
|
||
// DSIS Open reports Open errors to the user
|
||
REPORT_ERROR (TCP_DSIS_OPEN_FAIL, LOG_DEBUG);
|
||
return (Status);
|
||
}
|
||
|
||
REPORT_INFORMATION (TCP_DSIS_OPEN_SUCCESS, LOG_VERBOSE);
|
||
#endif // USE_DSIS
|
||
|
||
#ifdef LOAD_MGMTAPI // this STILL craps out
|
||
|
||
hMgmtApiDll = LoadLibrary ("MGMTAPI.DLL");
|
||
|
||
if (hMgmtApiDll == NULL) {
|
||
dwDataReturn[0] = GetLastError ();
|
||
REPORT_ERROR_DATA (TCP_LOAD_LIBRARY_FAIL, LOG_USER,
|
||
&dwDataReturn[0], (sizeof (DWORD)));
|
||
return (dwDataReturn[0]);
|
||
}
|
||
|
||
SnmpMgrStrToOid = GetProcAddress (hMgmtApiDll, "SnmpMgrStrToOid");
|
||
|
||
if (!(BOOL)SnmpMgrStrToOid) {
|
||
dwDataReturn[0] = GetLastError();
|
||
REPORT_ERROR_DATA (TCP_GET_STRTOOID_ADDR_FAIL, LOG_USER,
|
||
&dwDataReturn[0], (sizeof (DWORD)));
|
||
CloseNbtPerformanceData ();
|
||
FreeLibrary (hMgmtApiDll);
|
||
return (dwDataReturn[0]);
|
||
}
|
||
#else
|
||
|
||
// SnmpMgrStrToOid is defined as a macro above
|
||
|
||
#endif // LOAD_MGMTAPI
|
||
|
||
#ifdef LOAD_INETMIB1 // this STILL craps out
|
||
|
||
// don't pop up any dialog boxes
|
||
nErrorMode = SetErrorMode (SEM_FAILCRITICALERRORS);
|
||
|
||
hInetMibDll = LoadLibrary ("INETMIB1.DLL");
|
||
|
||
if (hInetMibDll == NULL) {
|
||
dwDataReturn[0] = GetLastError ();
|
||
REPORT_ERROR_DATA (TCP_LOAD_LIBRARY_FAIL, LOG_USER,
|
||
&dwDataReturn[0], (sizeof (DWORD)));
|
||
CloseNbtPerformanceData ();
|
||
// restore Error Mode
|
||
SetErrorMode (nErrorMode);
|
||
return (dwDataReturn[0]);
|
||
} else {
|
||
// restore Error Mode
|
||
SetErrorMode (nErrorMode);
|
||
}
|
||
|
||
pSnmpExtensionInit = (PFNSNMPEXTENSIONINIT)GetProcAddress
|
||
(hInetMibDll, "SnmpExtensionInit");
|
||
pSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY)GetProcAddress
|
||
(hInetMibDll, "SnmpExtensionQuery");
|
||
|
||
if (!pSnmpExtensionInit || !pSnmpExtensionQuery) {
|
||
dwDataReturn[0] = GetLastError();
|
||
REPORT_ERROR_DATA (TCP_LOAD_ROUTINE_FAIL, LOG_USER,
|
||
&dwDataReturn[0], (sizeof (DWORD)));
|
||
FreeLibrary (hInetMibDll);
|
||
CloseNbtPerformanceData ();
|
||
return (dwDataReturn[0]);
|
||
}
|
||
|
||
#endif // LOAD_INETMIB1
|
||
// Initialize the Variable Binding list for IP, ICMP, TCP and UDP
|
||
|
||
Status = 0; // initialize error count
|
||
|
||
HEAP_PROBE();
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
for (i = 0; i < NO_OF_OIDS; i++) {
|
||
if (!SnmpMgrStrToOid (OidStr[i], &(RefNames[i]))) {
|
||
Status++;
|
||
REPORT_ERROR_DATA (TCP_BAD_OBJECT, LOG_DEBUG,
|
||
OidStr[i], strlen(OidStr[i]));
|
||
RefNames[i].ids = NULL;
|
||
RefNames[i].idLength = 0;
|
||
}
|
||
RefVariableBindingsArray[i].value.asnType = ASN_NULL;
|
||
}
|
||
|
||
if (Status == 0) {
|
||
REPORT_INFORMATION (TCP_BINDINGS_INIT, LOG_VERBOSE);
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
|
||
// Initialize the Variable Binding list for Network interfaces
|
||
|
||
Status = 0;
|
||
for (i = 0; i < NO_OF_IF_OIDS; i++) {
|
||
if (!SnmpMgrStrToOid (IfOidStr[i], &(IFPermVariableBindingsArray[i].name))) {
|
||
Status++;
|
||
REPORT_ERROR_DATA (TCP_BAD_OBJECT, LOG_DEBUG,
|
||
IfOidStr[i], strlen(IfOidStr[i]));
|
||
}
|
||
|
||
IFPermVariableBindingsArray[i].value.asnType = ASN_NULL;
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
|
||
#ifdef LOAD_MGMTAPI
|
||
FreeLibrary (hMgmtApiDll); // done with SnmpMgrStrToOid routine
|
||
#endif
|
||
// initialize list structures
|
||
|
||
RefVariableBindings.list = RefVariableBindingsArray + OIDS_OFFSET;
|
||
RefVariableBindings.len = OIDS_LENGTH;
|
||
|
||
RefVariableBindingsICMP.list =
|
||
RefVariableBindingsArray + ICMP_OIDS_OFFSET;
|
||
RefVariableBindingsICMP.len = ICMP_OIDS_LENGTH;
|
||
|
||
RefIFVariableBindings.list = IFPermVariableBindingsArray;
|
||
RefIFVariableBindings.len = NO_OF_IF_OIDS;
|
||
#endif
|
||
|
||
if ( GetComputerName ((LPTSTR)ComputerName, (LPDWORD)&cchBuffer) == FALSE ) {
|
||
dwDataReturn[0] = GetLastError();
|
||
dwDataReturn[1] = 0;
|
||
REPORT_ERROR_DATA (TCP_COMPUTER_NAME, LOG_USER,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
CloseNbtPerformanceData ();
|
||
return dwDataReturn[0];
|
||
}
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
// enforce that TcpIpSession is on.
|
||
//
|
||
TcpIpSession = TRUE;
|
||
#else
|
||
#ifdef USE_SNMP
|
||
|
||
// Establish the SNMP connection to communicate with the local SNMP agent
|
||
|
||
/* This portion of the code for OpenTcpIpPerformanceData() could be used in
|
||
the CollectTcpIpPerformanceData() routine to open an SNMP Manager session
|
||
and collect data for the Network Interfaces, and IP, ICMP, TCP and UDP
|
||
protocols for a remote machine.
|
||
|
||
So, name this portion of the code: A
|
||
*/
|
||
|
||
if ( (TcpIpSession = SnmpMgrOpen ((LPSTR) ComputerName,
|
||
(LPSTR) "public",
|
||
TIMEOUT,
|
||
RETRIES)) == NULL ) {
|
||
dwDataReturn[0] = GetLastError();
|
||
REPORT_ERROR_DATA (TCP_SNMP_MGR_OPEN, LOG_USER,
|
||
&dwDataReturn, sizeof(DWORD));
|
||
return dwDataReturn[0];
|
||
}
|
||
|
||
/* End of code A
|
||
*/
|
||
#else
|
||
|
||
// if not using the standard SNMP interface, then TcpIpSession is
|
||
// a "boolean" to indicate if a session has been initialized and
|
||
// can therefore be used
|
||
|
||
TcpIpSession = FALSE; // make sure it's FALSE
|
||
|
||
// initialize inet mib routines
|
||
|
||
Status = (*pSnmpExtensionInit)(
|
||
0L,
|
||
&hSnmpEvent, // event is created by Init Routine
|
||
&SnmpOid
|
||
);
|
||
|
||
if (Status) {
|
||
TcpIpSession = TRUE; // return TRUE to indicate OK
|
||
}
|
||
|
||
#endif // USE_SNMP
|
||
#endif
|
||
|
||
bUseFriendlyNames = FriendlyNameIsSet();
|
||
}
|
||
dwTcpRefCount++;
|
||
|
||
HEAP_PROBE();
|
||
REPORT_INFORMATION (TCP_OPEN_PERFORMANCE_DATA, LOG_DEBUG);
|
||
return ERROR_SUCCESS;
|
||
} // OpenTcpIpPerformanceData
|
||
|
||
|
||
|
||
#pragma warning ( disable : 4127)
|
||
DWORD
|
||
CollectTcpIpPerformanceData(
|
||
LPWSTR lpValueName,
|
||
LPVOID *lppData,
|
||
LPDWORD lpcbTotalBytes,
|
||
LPDWORD lpNumObjectTypes
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine will return the data for all the TCP/IP counters.
|
||
|
||
Arguments:
|
||
|
||
Pointer to unicode string which is value passed to the registry for the
|
||
query.
|
||
|
||
Pointer to pointer to where to place the data.
|
||
|
||
Size in bytes of the data buffer.
|
||
|
||
|
||
Return Value:
|
||
|
||
Win32 Status. If successful, pointer to where to place the data
|
||
will be set to location following this routine's returned data block.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD Status;
|
||
|
||
// Variables for reformatting the TCP/IP data
|
||
|
||
register PDWORD pdwCounter, pdwPackets;
|
||
NET_INTERFACE_DATA_DEFINITION *pNetInterfaceDataDefinition;
|
||
IP_DATA_DEFINITION *pIpDataDefinition;
|
||
ICMP_DATA_DEFINITION *pIcmpDataDefinition;
|
||
TCP_DATA_DEFINITION *pTcpDataDefinition;
|
||
UDP_DATA_DEFINITION *pUdpDataDefinition;
|
||
DWORD SpaceNeeded;
|
||
UNICODE_STRING InterfaceName;
|
||
ANSI_STRING AnsiInterfaceName;
|
||
WCHAR InterfaceNameBuffer[MAX_INTERFACE_LEN+1];
|
||
CHAR AnsiInterfaceNameBuffer[MAX_INTERFACE_LEN+1];
|
||
register PERF_INSTANCE_DEFINITION *pPerfInstanceDefinition;
|
||
PERF_COUNTER_BLOCK *pPerfCounterBlock;
|
||
LPVOID lpDataTemp;
|
||
DWORD NumObjectTypesTemp;
|
||
|
||
LPWSTR lpFromString;
|
||
DWORD dwQueryType;
|
||
DWORD dwCounterFlags;
|
||
DWORD dwThisChar;
|
||
DWORD dwBlockSize;
|
||
|
||
// Variables for collecting the TCP/IP data
|
||
|
||
AsnInteger ErrorStatus;
|
||
AsnInteger ErrorIndex;
|
||
AsnInteger NetInterfaces;
|
||
AsnInteger Interface;
|
||
DWORD SentTemp;
|
||
DWORD ReceivedTemp;
|
||
|
||
DWORD dwDataReturn[2]; // for error values
|
||
BOOL bFreeName;
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
int i;
|
||
BOOL bStatus;
|
||
#if USE_SNMP
|
||
RFC1157VarBind IFVariableBindingsArray[NO_OF_IF_OIDS];
|
||
// The array of the variable bindings,
|
||
// used by the SNMP agent functions
|
||
// to record the info we want for each
|
||
// of the Network Interfaces
|
||
|
||
RFC1157VarBind *VBElem;
|
||
|
||
AsnInteger VBItem;
|
||
#endif
|
||
|
||
RFC1157VarBindList IFVariableBindings,
|
||
IFVariableBindingsCall,
|
||
VariableBindings,
|
||
VariableBindingsICMP;
|
||
// The header of the above list with
|
||
// the variable bindings.
|
||
#endif
|
||
|
||
//
|
||
// ***************** executable code starts here *******************
|
||
//
|
||
ErrorStatus = 0L;
|
||
ErrorIndex = 0L;
|
||
|
||
if (lpValueName == NULL) {
|
||
REPORT_INFORMATION (TCP_COLLECT_ENTERED, LOG_VERBOSE);
|
||
} else {
|
||
REPORT_INFORMATION_DATA (TCP_COLLECT_ENTERED, LOG_VERBOSE,
|
||
(LPVOID)lpValueName, (DWORD)(lstrlenW(lpValueName)*sizeof(WCHAR)));
|
||
}
|
||
//
|
||
// IF_DATA are all in DWORDS. We need to allow 1 of the octets which
|
||
// will be __int64
|
||
//
|
||
dwBlockSize = SIZE_OF_IF_DATA + (1 * sizeof(DWORD));
|
||
|
||
HEAP_PROBE();
|
||
//
|
||
// before doing anything else,
|
||
// see if this is a foreign (i.e. non-NT) computer data request
|
||
//
|
||
dwQueryType = GetQueryType (lpValueName);
|
||
|
||
if (dwQueryType == QUERY_FOREIGN) {
|
||
|
||
// find start of computer name to pass to CollectDsisPerformanceData
|
||
// this should put the pointer at the first character after the space
|
||
// presumably the computer name
|
||
|
||
lpFromString = lpValueName +
|
||
((sizeof(L"Foreign ")/sizeof(WCHAR))+1);
|
||
// check for double slash notation and move past if found
|
||
|
||
while (*lpFromString == '\\') {
|
||
lpFromString++;
|
||
}
|
||
|
||
//
|
||
// initialize local variables for sending to CollectDsisPerformanceData
|
||
// routine
|
||
//
|
||
lpDataTemp = *lppData;
|
||
SpaceNeeded = *lpcbTotalBytes;
|
||
NumObjectTypesTemp = *lpNumObjectTypes;
|
||
|
||
REPORT_INFORMATION_DATA (TCP_FOREIGN_COMPUTER_CMD, LOG_VERBOSE,
|
||
(LPVOID)lpFromString, (DWORD)(lstrlenW(lpFromString)*sizeof(WCHAR)));
|
||
#ifdef USE_DSIS
|
||
Status = CollectDsisPerformanceData (
|
||
lpFromString,
|
||
(LPVOID *) &lpDataTemp,
|
||
(LPDWORD) &SpaceNeeded,
|
||
(LPDWORD) &NumObjectTypesTemp);
|
||
//
|
||
// look at returned arguments to see if an error occured
|
||
// and send the appropriate event to the event log
|
||
//
|
||
if (Status == ERROR_SUCCESS) {
|
||
|
||
if (NumObjectTypesTemp > 0) {
|
||
REPORT_INFORMATION_DATA (TCP_DSIS_COLLECT_DATA_SUCCESS, LOG_DEBUG,
|
||
&NumObjectTypesTemp, sizeof (NumObjectTypesTemp));
|
||
} else {
|
||
REPORT_ERROR (TCP_DSIS_NO_OBJECTS, LOG_DEBUG);
|
||
}
|
||
|
||
//
|
||
// update main return variables
|
||
//
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
} else {
|
||
REPORT_ERROR_DATA (TCP_DSIS_COLLECT_DATA_ERROR, LOG_DEBUG,
|
||
&Status, sizeof (Status));
|
||
*lpcbTotalBytes = 0;
|
||
*lpNumObjectTypes = 0;
|
||
return Status;
|
||
}
|
||
#else
|
||
// no foreign data interface supported
|
||
*lpcbTotalBytes = 0;
|
||
*lpNumObjectTypes = 0;
|
||
return ERROR_SUCCESS;
|
||
#endif // USE_DSIS
|
||
} // endif QueryType == Foreign
|
||
|
||
dwCounterFlags = 0;
|
||
|
||
// determine what to return
|
||
|
||
if (dwQueryType == QUERY_GLOBAL) {
|
||
dwCounterFlags |= NBT_OBJECT;
|
||
dwCounterFlags |= SNMP_OBJECTS;
|
||
} else if (dwQueryType == QUERY_ITEMS) {
|
||
// check for the items provided by this routine
|
||
//
|
||
// Since the data requests for the following protocols are all
|
||
// bundled together, we'll send back all the data. Collecting it
|
||
// via SNMP is the hard part. once that's done, sending it back
|
||
// is trivial.
|
||
//
|
||
if (IsNumberInUnicodeList (TCP_OBJECT_TITLE_INDEX, lpValueName)) {
|
||
dwCounterFlags |= SNMP_OBJECTS;
|
||
} else if (IsNumberInUnicodeList (UDP_OBJECT_TITLE_INDEX, lpValueName)) {
|
||
dwCounterFlags |= SNMP_OBJECTS;
|
||
} else if (IsNumberInUnicodeList (IP_OBJECT_TITLE_INDEX, lpValueName)) {
|
||
dwCounterFlags |= SNMP_OBJECTS;
|
||
} else if (IsNumberInUnicodeList (ICMP_OBJECT_TITLE_INDEX, lpValueName)) {
|
||
dwCounterFlags |= SNMP_OBJECTS;
|
||
} else if (IsNumberInUnicodeList (NET_OBJECT_TITLE_INDEX, lpValueName)) {
|
||
dwCounterFlags |= SNMP_OBJECTS;
|
||
}
|
||
|
||
if (IsNumberInUnicodeList (NBT_OBJECT_TITLE_INDEX, lpValueName)) {
|
||
dwCounterFlags |= NBT_OBJECT;
|
||
}
|
||
}
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
// copy Binding array structures to working buffers for Snmp queries
|
||
|
||
RtlMoveMemory (VariableBindingsArray,
|
||
RefVariableBindingsArray,
|
||
sizeof (RefVariableBindingsArray));
|
||
|
||
VariableBindings.list = VariableBindingsArray + OIDS_OFFSET;
|
||
VariableBindings.len = OIDS_LENGTH;
|
||
|
||
VariableBindingsICMP.list = VariableBindingsArray + ICMP_OIDS_OFFSET;
|
||
VariableBindingsICMP.len = ICMP_OIDS_LENGTH;
|
||
#endif
|
||
if (DO_COUNTER_OBJECT (dwCounterFlags, NBT_OBJECT)) {
|
||
// Copy the parameters. We'll call the NBT Collect routine with these
|
||
// parameters
|
||
lpDataTemp = *lppData;
|
||
SpaceNeeded = *lpcbTotalBytes;
|
||
NumObjectTypesTemp = *lpNumObjectTypes;
|
||
|
||
// Collect NBT data
|
||
Status = CollectNbtPerformanceData (lpValueName,
|
||
(LPVOID *) &lpDataTemp,
|
||
(LPDWORD) &SpaceNeeded,
|
||
(LPDWORD) &NumObjectTypesTemp) ;
|
||
if (Status != ERROR_SUCCESS) {
|
||
// NBT Collection routine logs error messages to user
|
||
REPORT_ERROR_DATA (TCP_NBT_COLLECT_DATA, LOG_DEBUG,
|
||
&Status, sizeof (Status));
|
||
*lpcbTotalBytes = 0L;
|
||
*lpNumObjectTypes = 0L;
|
||
return Status;
|
||
}
|
||
} else {
|
||
// Initialize the parameters. We'll use these local
|
||
// parameters for remaining routines if NBT didn't use them
|
||
lpDataTemp = *lppData;
|
||
SpaceNeeded = 0;
|
||
NumObjectTypesTemp = 0;
|
||
}
|
||
|
||
/* To collect data for the Network Interfaces, and IP, ICMP, TCP and UDP
|
||
protocols for a remote machine whose name is in the Unicode string pointed
|
||
to by the lpValueName argument of CollectTcpIpData() routine, modify the
|
||
routine as follows:
|
||
|
||
1. Remove all the Nbt stuff from the code.
|
||
|
||
2. Convert the remote machine name from Unicode to Ansi, and have a local
|
||
LPSTR variable pointing to the Ansi remote machine name.
|
||
|
||
3. Place the above portion of the code named A after this comment.
|
||
|
||
4. Place the code named B (which is at the end of the file) at the end
|
||
of this routine to close the opened SNMP session.
|
||
|
||
*/
|
||
|
||
// get network info from SNMP agent
|
||
|
||
if ((dwCounterFlags & SNMP_OBJECTS) > 0) { // if any SNMP Objects selected
|
||
if (TRUE) { // and not a skeleton request
|
||
#ifdef USE_SNMP
|
||
if ( TcpIpSession == (LPSNMP_MGR_SESSION) NULL ) {
|
||
REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
#else
|
||
if (!TcpIpSession) {
|
||
REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
#endif
|
||
// Get the data for the IP, ICMP, TCP and UDP protocols, as well as
|
||
// the number of existing network interfaces.
|
||
|
||
// create local query list
|
||
|
||
HEAP_PROBE();
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
Status = GetNumberOfInterfaces(&IfNum);
|
||
if (Status)
|
||
{
|
||
dwDataReturn[0] = Status;
|
||
dwDataReturn[1] = 0;
|
||
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
Status = GetIpStatistics(&IpStats);
|
||
if (Status)
|
||
{
|
||
dwDataReturn[0] = Status;
|
||
dwDataReturn[1] = 0;
|
||
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
Status = GetTcpStatistics(&TcpStats);
|
||
if (Status)
|
||
{
|
||
dwDataReturn[0] = Status;
|
||
dwDataReturn[1] = 0;
|
||
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
Status = GetUdpStatistics(&UdpStats);
|
||
if (Status)
|
||
{
|
||
dwDataReturn[0] = Status;
|
||
dwDataReturn[1] = 0;
|
||
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
Status = GetIcmpStatistics(&IcmpStats);
|
||
if (Status)
|
||
{
|
||
dwDataReturn[0] = Status;
|
||
dwDataReturn[1] = 0;
|
||
REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
} // endif (TRUE)
|
||
#else
|
||
#ifdef USE_SNMP
|
||
SnmpUtilVarBindListCpy (&VariableBindings,
|
||
&RefVariableBindings);
|
||
#else
|
||
|
||
for (i = 0; i < NO_OF_OIDS; i++) {
|
||
SnmpUtilOidCpy (&(RefVariableBindingsArray[i].name),
|
||
&(RefNames[i]));
|
||
}
|
||
|
||
VariableBindings.list = RtlAllocateHeap (
|
||
RtlProcessHeap(),
|
||
0L,
|
||
(RefVariableBindings.len * sizeof(RFC1157VarBind)));
|
||
|
||
if (!VariableBindings.list) {
|
||
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
} else {
|
||
RtlMoveMemory (
|
||
VariableBindings.list,
|
||
RefVariableBindings.list,
|
||
(RefVariableBindings.len * sizeof(RFC1157VarBind)));
|
||
VariableBindings.len = RefVariableBindings.len;
|
||
}
|
||
#endif
|
||
|
||
HEAP_PROBE();
|
||
|
||
#ifdef USE_SNMP
|
||
bStatus = SnmpMgrRequest (TcpIpSession,
|
||
ASN_RFC1157_GETREQUEST,
|
||
&VariableBindings,
|
||
&ErrorStatus,
|
||
&ErrorIndex);
|
||
#else
|
||
bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETREQUEST,
|
||
&VariableBindings,
|
||
&ErrorStatus,
|
||
&ErrorIndex);
|
||
#endif
|
||
if ( !bStatus ) {
|
||
dwDataReturn[0] = ErrorStatus;
|
||
dwDataReturn[1] = ErrorIndex;
|
||
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
|
||
if ( ErrorStatus > 0 ) {
|
||
dwDataReturn[0] = ErrorStatus;
|
||
dwDataReturn[1] = ErrorIndex;
|
||
REPORT_ERROR_DATA (TCP_SNMP_MGR_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
|
||
#ifdef USE_SNMP
|
||
SnmpUtilVarBindListCpy (&VariableBindingsICMP,
|
||
&RefVariableBindingsICMP);
|
||
#else
|
||
VariableBindingsICMP.list = RtlAllocateHeap (
|
||
RtlProcessHeap(),
|
||
0L,
|
||
(RefVariableBindingsICMP.len * sizeof(RFC1157VarBind)));
|
||
|
||
if (!VariableBindingsICMP.list) {
|
||
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded;
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
} else {
|
||
RtlMoveMemory (
|
||
VariableBindingsICMP.list,
|
||
RefVariableBindingsICMP.list,
|
||
(RefVariableBindingsICMP.len * sizeof(RFC1157VarBind)));
|
||
VariableBindingsICMP.len = RefVariableBindingsICMP.len;
|
||
}
|
||
#endif
|
||
|
||
HEAP_PROBE();
|
||
|
||
#ifdef USE_SNMP
|
||
bStatus = SnmpMgrRequest (TcpIpSession,
|
||
ASN_RFC1157_GETREQUEST,
|
||
&VariableBindingsICMP,
|
||
&ErrorStatus,
|
||
|
||
#else
|
||
bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETREQUEST,
|
||
&VariableBindingsICMP,
|
||
&ErrorStatus,
|
||
&ErrorIndex);
|
||
#endif
|
||
|
||
if ( !bStatus ) {
|
||
dwDataReturn[0] = ErrorStatus;
|
||
dwDataReturn[1] = ErrorIndex;
|
||
REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
SnmpUtilVarBindListFree (&VariableBindingsICMP);
|
||
|
||
return ERROR_SUCCESS;
|
||
}
|
||
if ( ErrorStatus > 0 ) {
|
||
dwDataReturn[0] = ErrorStatus;
|
||
dwDataReturn[1] = ErrorIndex;
|
||
REPORT_ERROR_DATA (TCP_ICMP_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
SnmpUtilVarBindListFree (&VariableBindingsICMP);
|
||
|
||
return ERROR_SUCCESS;
|
||
}
|
||
} // endif (TRUE)
|
||
|
||
HEAP_PROBE();
|
||
|
||
// make sure everything made it back OK
|
||
|
||
if (VariableBindingsICMP.list == 0) {
|
||
REPORT_WARNING (TCP_NULL_ICMP_BUFF, LOG_DEBUG);
|
||
dwCounterFlags |= (SNMP_ERROR); // return null data
|
||
}
|
||
|
||
if (VariableBindings.list == 0) {
|
||
REPORT_WARNING (TCP_NULL_TCP_BUFF, LOG_DEBUG);
|
||
dwCounterFlags |= (SNMP_ERROR); // return null data
|
||
dwCounterFlags &= ~NET_OBJECT; // don't do NET Interface ctrs.
|
||
}
|
||
#endif
|
||
|
||
if (DO_COUNTER_OBJECT(dwCounterFlags, SNMP_ERROR)) {
|
||
REPORT_WARNING (TCP_NULL_SNMP_BUFF, LOG_USER);
|
||
}
|
||
|
||
if (DO_COUNTER_OBJECT (dwCounterFlags, NET_OBJECT)) {
|
||
|
||
SpaceNeeded += sizeof (NET_INTERFACE_DATA_DEFINITION);
|
||
if ( *lpcbTotalBytes < SpaceNeeded ) {
|
||
dwDataReturn[0] = *lpcbTotalBytes;
|
||
dwDataReturn[1] = SpaceNeeded;
|
||
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
//
|
||
// if the buffer size is too small here, throw everything
|
||
// away (including the NBT stuff) and return buffer size
|
||
// error. If all goes well the caller will call back shortly
|
||
// with a larger buffer and everything will be re-collected.
|
||
//
|
||
*lpcbTotalBytes = 0;
|
||
*lpNumObjectTypes = 0;
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
SnmpUtilVarBindListFree (&VariableBindingsICMP);
|
||
#endif
|
||
return ERROR_MORE_DATA;
|
||
}
|
||
|
||
pNetInterfaceDataDefinition =
|
||
(NET_INTERFACE_DATA_DEFINITION *) lpDataTemp;
|
||
|
||
RtlMoveMemory (pNetInterfaceDataDefinition,
|
||
&NetInterfaceDataDefinition,
|
||
sizeof (NET_INTERFACE_DATA_DEFINITION));
|
||
|
||
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
|
||
(pNetInterfaceDataDefinition + 1);
|
||
#ifdef USE_IPHLPAPI
|
||
NetInterfaces = IfNum;
|
||
#else
|
||
NetInterfaces =
|
||
VariableBindings.list[IF_NUMBER_INDEX].value.asnValue.number;
|
||
#endif
|
||
|
||
REPORT_INFORMATION_DATA (TCP_NET_INTERFACE, LOG_VERBOSE,
|
||
&NetInterfaces, sizeof(NetInterfaces));
|
||
|
||
if ( NetInterfaces ) {
|
||
|
||
// Initialize the Variable Binding list for the
|
||
// Network Interface Performance Data
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
HEAP_PROBE();
|
||
#ifdef USE_SNMP
|
||
SnmpUtilVarBindListCpy (&IFVariableBindings,
|
||
&RefIFVariableBindings);
|
||
#else
|
||
|
||
SnmpUtilVarBindListCpy (&IFVariableBindingsCall,
|
||
&RefIFVariableBindings);
|
||
|
||
IFVariableBindings.list = RtlAllocateHeap (
|
||
RtlProcessHeap(),
|
||
0L,
|
||
(RefIFVariableBindings.len * sizeof(RFC1157VarBind)));
|
||
|
||
if (!IFVariableBindings.list) {
|
||
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
} else {
|
||
RtlMoveMemory (
|
||
IFVariableBindings.list,
|
||
IFVariableBindingsCall.list,
|
||
(IFVariableBindingsCall.len * sizeof(RFC1157VarBind)));
|
||
IFVariableBindings.len = RefIFVariableBindings.len;
|
||
}
|
||
#endif
|
||
#endif
|
||
HEAP_PROBE();
|
||
|
||
// Initialize buffer for the network interfaces' names
|
||
|
||
AnsiInterfaceName.Length =
|
||
AnsiInterfaceName.MaximumLength = MAX_INTERFACE_LEN + 1;
|
||
AnsiInterfaceName.Buffer = AnsiInterfaceNameBuffer;
|
||
|
||
}
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
|
||
Status = GetNumberOfInterfaces(&NetInterfaces);
|
||
if ((Status != ERROR_SUCCESS) || (NetInterfaces < DEFAULT_INTERFACES)) {
|
||
NetInterfaces = DEFAULT_INTERFACES;
|
||
}
|
||
IfTableSize = SIZEOF_IFTABLE(NetInterfaces);
|
||
Status = ERROR_INSUFFICIENT_BUFFER;
|
||
SentTemp = 0;
|
||
IfTable = NULL;
|
||
while ((Status == ERROR_INSUFFICIENT_BUFFER) &&
|
||
(SentTemp++ < 10)) {
|
||
if (IfTable) {
|
||
HeapFree(RtlProcessHeap(), 0L, IfTable);
|
||
}
|
||
IfTable = (PMIB_IFTABLE) RtlAllocateHeap(
|
||
RtlProcessHeap(), 0L, IfTableSize);
|
||
if (!IfTable)
|
||
{
|
||
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
Status = GetIfTable(IfTable, & IfTableSize, FALSE);
|
||
}
|
||
if (Status)
|
||
{
|
||
dwDataReturn[0] = Status;
|
||
dwDataReturn[1] = 0;
|
||
REPORT_ERROR_DATA (TCP_NET_GETNEXT_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
#ifdef USE_IPHLPAPI
|
||
if (IfTable) {
|
||
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
|
||
IfTable = NULL;
|
||
}
|
||
#endif
|
||
*lppData = ALIGN_ON_QWORD(lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
NetInterfaces = IfTable->dwNumEntries;
|
||
#endif
|
||
// Loop for every network interface
|
||
|
||
for ( Interface = 0; Interface < NetInterfaces; Interface++ ) {
|
||
|
||
// Get the data for the network interface
|
||
HEAP_PROBE();
|
||
#ifndef USE_IPHLPAPI
|
||
#ifdef USE_SNMP
|
||
bStatus = SnmpMgrRequest ( TcpIpSession,
|
||
ASN_RFC1157_GETNEXTREQUEST,
|
||
&IFVariableBindings,
|
||
&ErrorStatus,
|
||
&ErrorIndex);
|
||
#else
|
||
bStatus = (*pSnmpExtensionQuery) (ASN_RFC1157_GETNEXTREQUEST,
|
||
&IFVariableBindings,
|
||
&ErrorStatus,
|
||
&ErrorIndex);
|
||
#endif
|
||
HEAP_PROBE();
|
||
|
||
if ( ! bStatus ) {
|
||
continue;
|
||
}
|
||
|
||
if ( ErrorStatus > 0 ) {
|
||
dwDataReturn[0] = ErrorStatus;
|
||
dwDataReturn[1] = ErrorIndex;
|
||
REPORT_ERROR_DATA (TCP_NET_GETNEXT_REQUEST, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
continue;
|
||
}
|
||
#endif
|
||
|
||
bFreeName = FALSE;
|
||
// Everything is fine, so go get the data (prepare a new instance)
|
||
#ifdef USE_IPHLPAPI
|
||
RtlInitAnsiString(&AnsiInterfaceName, IfTable->table[Interface].bDescr);
|
||
#else
|
||
AnsiInterfaceName.Length = (USHORT)sprintf (AnsiInterfaceNameBuffer,
|
||
"%ld",
|
||
IFVariableBindings.list[IF_INDEX_INDEX].value.asnValue.number);
|
||
#endif
|
||
|
||
if (AnsiInterfaceName.Length <= MAX_INTERFACE_LEN) {
|
||
RtlInitUnicodeString(&InterfaceName, NULL);
|
||
RtlAnsiStringToUnicodeString(
|
||
&InterfaceName,
|
||
&AnsiInterfaceName,
|
||
TRUE);
|
||
bFreeName = TRUE;
|
||
}
|
||
else {
|
||
InterfaceName.Length =
|
||
InterfaceName.MaximumLength = (MAX_INTERFACE_LEN + 1) * sizeof (WCHAR);
|
||
InterfaceName.Buffer = InterfaceNameBuffer;
|
||
|
||
RtlAnsiStringToUnicodeString (&InterfaceName,
|
||
&AnsiInterfaceName,
|
||
FALSE);
|
||
}
|
||
SpaceNeeded += sizeof (PERF_INSTANCE_DEFINITION) +
|
||
QWORD_MULTIPLE(InterfaceName.Length+sizeof(UNICODE_NULL)) +
|
||
dwBlockSize;
|
||
|
||
if ( *lpcbTotalBytes < SpaceNeeded ) {
|
||
dwDataReturn[0] = *lpcbTotalBytes;
|
||
dwDataReturn[1] = SpaceNeeded;
|
||
REPORT_WARNING_DATA (TCP_NET_BUFFER_SIZE, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
//
|
||
// if the buffer size is too small here, throw everything
|
||
// away (including the NBT stuff) and return buffer size
|
||
// error. If all goes well the caller will call back shortly
|
||
// with a larger buffer and everything will be re-collected.
|
||
//
|
||
*lpcbTotalBytes = 0;
|
||
*lpNumObjectTypes = 0;
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
SnmpUtilVarBindListFree (&IFVariableBindings);
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
SnmpUtilVarBindListFree (&VariableBindingsICMP);
|
||
#else
|
||
if (IfTable) {
|
||
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
|
||
IfTable = NULL;
|
||
}
|
||
#endif
|
||
|
||
return ERROR_MORE_DATA;
|
||
}
|
||
|
||
if (bUseFriendlyNames) {
|
||
// replace any reserved characters in the instance name with safe ones
|
||
for (dwThisChar = 0; dwThisChar <= (InterfaceName.Length / sizeof (WCHAR)); dwThisChar++) {
|
||
switch (InterfaceName.Buffer[dwThisChar]) {
|
||
case L'(': InterfaceName.Buffer[dwThisChar] = L'['; break;
|
||
case L')': InterfaceName.Buffer[dwThisChar] = L']'; break;
|
||
case L'#': InterfaceName.Buffer[dwThisChar] = L'_'; break;
|
||
case L'/': InterfaceName.Buffer[dwThisChar] = L'_'; break;
|
||
case L'\\': InterfaceName.Buffer[dwThisChar] = L'_'; break;
|
||
default: break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
MonBuildInstanceDefinition (pPerfInstanceDefinition,
|
||
(PVOID *) &pPerfCounterBlock,
|
||
0,
|
||
0,
|
||
(bUseFriendlyNames ? (DWORD)PERF_NO_UNIQUE_ID : (DWORD)(Interface + 1)),
|
||
&InterfaceName);
|
||
|
||
if (bFreeName) {
|
||
RtlFreeUnicodeString(&InterfaceName);
|
||
}
|
||
pPerfCounterBlock->ByteLength = dwBlockSize;
|
||
|
||
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
Assign64( IfTable->table[Interface].dwInOctets
|
||
+ IfTable->table[Interface].dwOutOctets,
|
||
(PLARGE_INTEGER) pdwCounter);
|
||
|
||
REPORT_INFORMATION (TCP_COPYING_DATA, LOG_VERBOSE);
|
||
|
||
pdwPackets = pdwCounter + 2;
|
||
|
||
pdwCounter += 4; // skip packet counters first
|
||
|
||
*++pdwCounter = IfTable->table[Interface].dwSpeed;
|
||
*++pdwCounter = IfTable->table[Interface].dwInOctets;
|
||
|
||
ReceivedTemp = *++pdwCounter = IfTable->table[Interface].dwInUcastPkts;
|
||
ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInNUcastPkts;
|
||
ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInDiscards;
|
||
ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInErrors;
|
||
ReceivedTemp += *++pdwCounter = IfTable->table[Interface].dwInUnknownProtos;
|
||
*++pdwCounter = IfTable->table[Interface].dwOutOctets;
|
||
SentTemp = *++pdwCounter = IfTable->table[Interface].dwOutUcastPkts;
|
||
SentTemp += *++pdwCounter = IfTable->table[Interface].dwOutNUcastPkts;
|
||
*++pdwCounter = IfTable->table[Interface].dwOutDiscards;
|
||
*++pdwCounter = IfTable->table[Interface].dwOutErrors;
|
||
*++pdwCounter = IfTable->table[Interface].dwOutQLen;
|
||
#else
|
||
Assign64( IF_COUNTER(IF_INOCTETS_INDEX) +
|
||
IF_COUNTER(IF_OUTOCTETS_INDEX,
|
||
(PLARGE_INTEGER) pdwCounter);
|
||
|
||
REPORT_INFORMATION (TCP_COPYING_DATA, LOG_VERBOSE);
|
||
|
||
pdwPackets = pdwCounter + 2;
|
||
pdwCounter += 4; // skip packet counters first
|
||
//
|
||
// NOTE: We are skipping 2 words for Total bytes,
|
||
// and one each for total packets, in packets & out packets
|
||
//
|
||
|
||
*++pdwCounter = IF_GAUGE(IF_SPEED_INDEX);
|
||
*++pdwCounter = IF_COUNTER(IF_INOCTETS_INDEX);
|
||
|
||
ReceivedTemp = *++pdwCounter = IF_COUNTER(IF_INUCASTPKTS_INDEX);
|
||
ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INNUCASTPKTS_INDEX);
|
||
ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INDISCARDS_INDEX);
|
||
ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INERRORS_INDEX);
|
||
ReceivedTemp += *++pdwCounter = IF_COUNTER(IF_INUNKNOWNPROTOS_INDEX);
|
||
*++pdwCounter = IF_COUNTER(IF_OUTOCTETS_INDEX);
|
||
|
||
SentTemp = *pdwCounter = IF_COUNTER(IF_OUTUCASTPKTS_INDEX);
|
||
SentTemp += *++pdwCounter = IF_COUNTER(IF_OUTNUCASTPKTS_INDEX);
|
||
*++pdwCounter = IF_COUNTER(IF_OUTDISCARDS_INDEX);
|
||
*++pdwCounter = IF_COUNTER(IF_OUTERRORS_INDEX);
|
||
*++pdwCounter = IF_COUNTER(IF_OUTQLEN_INDEX);
|
||
#endif
|
||
*pdwPackets = ReceivedTemp + SentTemp;
|
||
*++pdwPackets = ReceivedTemp;
|
||
*++pdwPackets = SentTemp;
|
||
|
||
pPerfInstanceDefinition = (PERF_INSTANCE_DEFINITION *)
|
||
(((PBYTE) pPerfCounterBlock) + dwBlockSize);
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
#if USE_SNMP
|
||
// Prepare to get the data for the next network interface
|
||
|
||
if ( Interface < NetInterfaces ) {
|
||
|
||
for ( i = 0; i < NO_OF_IF_OIDS; i++ ) {
|
||
|
||
// SnmpUtilOidFree (&IFVariableBindingsArray[i].name);
|
||
|
||
SnmpUtilOidCpy (&IFVariableBindingsArray[i].name,
|
||
&IFVariableBindings.list[i].name);
|
||
}
|
||
}
|
||
|
||
SnmpUtilVarBindListFree (&IFVariableBindings);
|
||
|
||
IFVariableBindings.list = IFVariableBindingsArray;
|
||
IFVariableBindings.len = NO_OF_IF_OIDS;
|
||
#else
|
||
if ( Interface < NetInterfaces ) {
|
||
|
||
// since SnmpExtesionQuery returned newly allocated
|
||
// OID buffers, we need to:
|
||
// 1. free the original OID Buffers
|
||
// 2. copy the new into the old
|
||
// 3. free the returned buffers (OID's and data)
|
||
// 4. realloc a clean "new" buffer and
|
||
// 5. copy the new OIDS (with empty data) into
|
||
// new buffer
|
||
|
||
for ( i = 0; i < NO_OF_IF_OIDS; i++ ) {
|
||
|
||
// SnmpUtilOidFree (&IFVariableBindingsCall.list[i].name);
|
||
|
||
SnmpUtilOidCpy (&IFVariableBindingsCall.list[i].name,
|
||
&IFVariableBindings.list[i].name);
|
||
|
||
}
|
||
SnmpUtilVarBindListFree (&IFVariableBindings);
|
||
|
||
IFVariableBindings.list = RtlAllocateHeap (
|
||
RtlProcessHeap(),
|
||
0L,
|
||
(RefIFVariableBindings.len * sizeof(RFC1157VarBind)));
|
||
|
||
if (!VariableBindings.list) {
|
||
REPORT_ERROR (TCP_SNMP_BUFFER_ALLOC_FAIL, LOG_DEBUG);
|
||
*lppData = lpDataTemp;
|
||
*lpcbTotalBytes = SpaceNeeded;
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
#ifdef USE_IPHLPAPI
|
||
if (IfTable) {
|
||
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
|
||
IfTable = NULL;
|
||
}
|
||
#endif
|
||
return ERROR_SUCCESS;
|
||
} else {
|
||
RtlMoveMemory (
|
||
IFVariableBindings.list,
|
||
IFVariableBindingsCall.list,
|
||
(IFVariableBindingsCall.len * sizeof(RFC1157VarBind)));
|
||
IFVariableBindings.len = RefIFVariableBindings.len;
|
||
}
|
||
}
|
||
|
||
#endif
|
||
#endif
|
||
HEAP_PROBE();
|
||
}
|
||
|
||
pNetInterfaceDataDefinition->NetInterfaceObjectType.TotalByteLength =
|
||
(DWORD)((PBYTE) pPerfInstanceDefinition - (PBYTE) pNetInterfaceDataDefinition);
|
||
|
||
pNetInterfaceDataDefinition->NetInterfaceObjectType.NumInstances =
|
||
NetInterfaces;
|
||
|
||
// setup counters and pointers for next counter
|
||
|
||
NumObjectTypesTemp += 1;
|
||
lpDataTemp = (LPVOID)pPerfInstanceDefinition;
|
||
// SpaceNeeded is kept up already
|
||
|
||
HEAP_PROBE();
|
||
|
||
if ( NetInterfaces ) {
|
||
#ifndef USE_IPHLPAPI
|
||
SnmpUtilVarBindListFree (&IFVariableBindings);
|
||
// SnmpUtilVarBindListFree (&IFVariableBindingsCall);
|
||
RtlFreeHeap (RtlProcessHeap(), 0L, IFVariableBindingsCall.list);
|
||
#endif
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
|
||
} // end if Net Counters
|
||
|
||
// Get IP data
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
if (IfTable) {
|
||
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
|
||
IfTable = NULL;
|
||
}
|
||
#endif
|
||
|
||
HEAP_PROBE();
|
||
|
||
if (DO_COUNTER_OBJECT (dwCounterFlags, IP_OBJECT)) {
|
||
|
||
SpaceNeeded += (sizeof(IP_DATA_DEFINITION) + SIZE_OF_IP_DATA);
|
||
|
||
if ( *lpcbTotalBytes < SpaceNeeded ) {
|
||
dwDataReturn[0] = *lpcbTotalBytes;
|
||
dwDataReturn[1] = SpaceNeeded;
|
||
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
//
|
||
// if the buffer size is too small here, throw everything
|
||
// away (including the NBT stuff) and return buffer size
|
||
// error. If all goes well the caller will call back shortly
|
||
// with a larger buffer and everything will be re-collected.
|
||
//
|
||
*lpcbTotalBytes = 0;
|
||
*lpNumObjectTypes = 0;
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
SnmpUtilVarBindListFree (&VariableBindingsICMP);
|
||
#endif
|
||
return ERROR_MORE_DATA;
|
||
}
|
||
|
||
pIpDataDefinition = (IP_DATA_DEFINITION *) lpDataTemp;
|
||
|
||
RtlMoveMemory (pIpDataDefinition,
|
||
&IpDataDefinition,
|
||
sizeof (IP_DATA_DEFINITION));
|
||
|
||
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pIpDataDefinition + 1);
|
||
pPerfCounterBlock->ByteLength = SIZE_OF_IP_DATA;
|
||
|
||
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
*pdwCounter = IpStats.dwInReceives + IpStats.dwOutRequests;
|
||
*++pdwCounter = IpStats.dwInReceives;
|
||
*++pdwCounter = IpStats.dwInHdrErrors;
|
||
*++pdwCounter = IpStats.dwInAddrErrors;
|
||
*++pdwCounter = IpStats.dwForwDatagrams;
|
||
*++pdwCounter = IpStats.dwInUnknownProtos;
|
||
*++pdwCounter = IpStats.dwInDiscards;
|
||
*++pdwCounter = IpStats.dwInDelivers;
|
||
*++pdwCounter = IpStats.dwOutRequests;
|
||
*++pdwCounter = IpStats.dwOutDiscards;
|
||
*++pdwCounter = IpStats.dwOutNoRoutes;
|
||
*++pdwCounter = IpStats.dwReasmReqds;
|
||
*++pdwCounter = IpStats.dwReasmOks;
|
||
*++pdwCounter = IpStats.dwReasmFails;
|
||
*++pdwCounter = IpStats.dwFragOks;
|
||
*++pdwCounter = IpStats.dwFragFails;
|
||
*++pdwCounter = IpStats.dwFragCreates;
|
||
#else
|
||
*pdwCounter = IP_COUNTER(IP_INRECEIVES_INDEX) +
|
||
IP_COUNTER(IP_OUTREQUESTS_INDEX);
|
||
|
||
*++pdwCounter = IP_COUNTER(IP_INRECEIVES_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_INHDRERRORS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_INADDRERRORS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_FORWDATAGRAMS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_INUNKNOWNPROTOS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_INDISCARDS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_INDELIVERS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_OUTREQUESTS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_OUTDISCARDS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_OUTNOROUTES_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_REASMREQDS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_REASMOKS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_REASMFAILS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_FRAGOKS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_FRAGFAILS_INDEX);
|
||
*++pdwCounter = IP_COUNTER(IP_FRAGCREATES_INDEX);
|
||
#endif
|
||
// setup counters and pointers for next counter
|
||
|
||
NumObjectTypesTemp +=1;
|
||
lpDataTemp = (LPVOID)++pdwCounter;
|
||
// SpaceNeeded is kept up already
|
||
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
|
||
// Get ICMP data
|
||
|
||
if (DO_COUNTER_OBJECT (dwCounterFlags, ICMP_OBJECT)) {
|
||
// The data for the network interfaces are now ready. So, let's get
|
||
// the data for the IP, ICMP, TCP and UDP protocols.
|
||
|
||
SpaceNeeded += (sizeof(ICMP_DATA_DEFINITION) + SIZE_OF_ICMP_DATA);
|
||
|
||
if ( *lpcbTotalBytes < SpaceNeeded ) {
|
||
dwDataReturn[0] = *lpcbTotalBytes;
|
||
dwDataReturn[1] = SpaceNeeded;
|
||
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
//
|
||
// if the buffer size is too small here, throw everything
|
||
// away (including the NBT stuff) and return buffer size
|
||
// error. If all goes well the caller will call back shortly
|
||
// with a larger buffer and everything will be re-collected.
|
||
//
|
||
*lpcbTotalBytes = 0;
|
||
*lpNumObjectTypes = 0;
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
SnmpUtilVarBindListFree (&VariableBindingsICMP);
|
||
#endif
|
||
return ERROR_MORE_DATA;
|
||
}
|
||
|
||
pIcmpDataDefinition = (ICMP_DATA_DEFINITION *) lpDataTemp;;
|
||
|
||
RtlMoveMemory (pIcmpDataDefinition,
|
||
&IcmpDataDefinition,
|
||
sizeof (ICMP_DATA_DEFINITION));
|
||
|
||
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pIcmpDataDefinition + 1);
|
||
pPerfCounterBlock->ByteLength = SIZE_OF_ICMP_DATA;
|
||
|
||
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
*pdwCounter = IcmpStats.stats.icmpInStats.dwMsgs
|
||
+ IcmpStats.stats.icmpOutStats.dwMsgs;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwMsgs;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwErrors;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwDestUnreachs;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwTimeExcds;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwParmProbs;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwSrcQuenchs;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwRedirects;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwEchos;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwEchoReps;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwTimestamps;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwTimestampReps;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwAddrMasks;
|
||
*++pdwCounter = IcmpStats.stats.icmpInStats.dwAddrMaskReps;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwMsgs;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwErrors;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwDestUnreachs;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimeExcds;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwParmProbs;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwSrcQuenchs;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwRedirects;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwEchos;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwEchoReps;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimestamps;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwTimestampReps;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwAddrMasks;
|
||
*++pdwCounter = IcmpStats.stats.icmpOutStats.dwAddrMaskReps;
|
||
#else
|
||
*pdwCounter = ICMP_COUNTER(ICMP_INMSGS_INDEX) +
|
||
ICMP_COUNTER(ICMP_OUTMSGS_INDEX);
|
||
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INMSGS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INERRORS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INDESTUNREACHS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INTIMEEXCDS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INPARMPROBS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INSRCQUENCHS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INREDIRECTS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INECHOS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INECHOREPS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INTIMESTAMPS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INTIMESTAMPREPS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INADDRMASKS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_INADDRMASKREPS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTMSGS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTERRORS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTDESTUNREACHS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMEEXCDS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTPARMPROBS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTSRCQUENCHS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTREDIRECTS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTECHOS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTECHOREPS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMESTAMPS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTTIMESTAMPREPS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTADDRMASKS_INDEX);
|
||
*++pdwCounter = ICMP_COUNTER(ICMP_OUTADDRMASKREPS_INDEX);
|
||
#endif
|
||
|
||
HEAP_PROBE();
|
||
|
||
// SnmpUtilVarBindListFree (&VariableBindingsICMP);
|
||
|
||
HEAP_PROBE();
|
||
|
||
// setup counters and pointers for next counter
|
||
|
||
NumObjectTypesTemp += 1;
|
||
lpDataTemp = (LPVOID)++pdwCounter;
|
||
// SpaceNeeded is kept up already
|
||
|
||
}
|
||
#ifndef USE_IPHLPAPI
|
||
SnmpUtilVarBindListFree (&VariableBindingsICMP);
|
||
#endif
|
||
|
||
HEAP_PROBE();
|
||
|
||
// Get TCP data
|
||
|
||
if (DO_COUNTER_OBJECT (dwCounterFlags, TCP_OBJECT)) {
|
||
|
||
// The data for the network interfaces are now ready. So, let's get
|
||
// the data for the IP, ICMP, TCP and UDP protocols.
|
||
|
||
SpaceNeeded += (sizeof(TCP_DATA_DEFINITION) + SIZE_OF_TCP_DATA);
|
||
|
||
if ( *lpcbTotalBytes < SpaceNeeded ) {
|
||
dwDataReturn[0] = *lpcbTotalBytes;
|
||
dwDataReturn[1] = SpaceNeeded;
|
||
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
//
|
||
// if the buffer size is too small here, throw everything
|
||
// away (including the NBT stuff) and return buffer size
|
||
// error. If all goes well the caller will call back shortly
|
||
// with a larger buffer and everything will be re-collected.
|
||
//
|
||
*lpcbTotalBytes = 0;
|
||
*lpNumObjectTypes = 0;
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
#endif
|
||
return ERROR_MORE_DATA;
|
||
}
|
||
|
||
pTcpDataDefinition = (TCP_DATA_DEFINITION *) lpDataTemp;
|
||
|
||
RtlMoveMemory (pTcpDataDefinition,
|
||
&TcpDataDefinition,
|
||
sizeof (TCP_DATA_DEFINITION));
|
||
|
||
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pTcpDataDefinition + 1);
|
||
pPerfCounterBlock->ByteLength = SIZE_OF_TCP_DATA;
|
||
|
||
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
*pdwCounter = TcpStats.dwInSegs + TcpStats.dwOutSegs;
|
||
*++pdwCounter = TcpStats.dwCurrEstab;
|
||
*++pdwCounter = TcpStats.dwActiveOpens;
|
||
*++pdwCounter = TcpStats.dwPassiveOpens;
|
||
*++pdwCounter = TcpStats.dwAttemptFails;
|
||
*++pdwCounter = TcpStats.dwEstabResets;
|
||
*++pdwCounter = TcpStats.dwInSegs;
|
||
*++pdwCounter = TcpStats.dwOutSegs;
|
||
*++pdwCounter = TcpStats.dwRetransSegs;
|
||
#else
|
||
*pdwCounter = TCP_COUNTER(TCP_INSEGS_INDEX) +
|
||
TCP_COUNTER(TCP_OUTSEGS_INDEX);
|
||
|
||
*++pdwCounter = TCP_GAUGE(TCP_CURRESTAB_INDEX);
|
||
*++pdwCounter = TCP_COUNTER(TCP_ACTIVEOPENS_INDEX);
|
||
*++pdwCounter = TCP_COUNTER(TCP_PASSIVEOPENS_INDEX);
|
||
*++pdwCounter = TCP_COUNTER(TCP_ATTEMPTFAILS_INDEX);
|
||
*++pdwCounter = TCP_COUNTER(TCP_ESTABRESETS_INDEX);
|
||
*++pdwCounter = TCP_COUNTER(TCP_INSEGS_INDEX);
|
||
*++pdwCounter = TCP_COUNTER(TCP_OUTSEGS_INDEX);
|
||
*++pdwCounter = TCP_COUNTER(TCP_RETRANSSEGS_INDEX);
|
||
#endif
|
||
// setup counters and pointers for next counter
|
||
|
||
NumObjectTypesTemp += 1;
|
||
lpDataTemp = (LPVOID)++pdwCounter;
|
||
// SpaceNeeded is kept up already
|
||
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
|
||
// Get UDP data
|
||
|
||
if (DO_COUNTER_OBJECT (dwCounterFlags, UDP_OBJECT)) {
|
||
|
||
// The data for the network interfaces are now ready. So, let's get
|
||
// the data for the IP, ICMP, TCP and UDP protocols.
|
||
|
||
SpaceNeeded += (sizeof(UDP_DATA_DEFINITION) + SIZE_OF_UDP_DATA);
|
||
|
||
if ( *lpcbTotalBytes < SpaceNeeded ) {
|
||
dwDataReturn[0] = *lpcbTotalBytes;
|
||
dwDataReturn[1] = SpaceNeeded;
|
||
REPORT_WARNING_DATA (TCP_NET_IF_BUFFER_SIZE, LOG_DEBUG,
|
||
&dwDataReturn, sizeof(dwDataReturn));
|
||
//
|
||
// if the buffer size is too small here, throw everything
|
||
// away (including the NBT stuff) and return buffer size
|
||
// error. If all goes well the caller will call back shortly
|
||
// with a larger buffer and everything will be re-collected.
|
||
//
|
||
*lpcbTotalBytes = 0;
|
||
*lpNumObjectTypes = 0;
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
#endif
|
||
return ERROR_MORE_DATA;
|
||
}
|
||
|
||
pUdpDataDefinition = (UDP_DATA_DEFINITION *) lpDataTemp;
|
||
|
||
RtlMoveMemory (pUdpDataDefinition,
|
||
&UdpDataDefinition,
|
||
sizeof (UDP_DATA_DEFINITION));
|
||
|
||
pPerfCounterBlock = (PERF_COUNTER_BLOCK *) (pUdpDataDefinition + 1);
|
||
pPerfCounterBlock->ByteLength = SIZE_OF_UDP_DATA;
|
||
|
||
pdwCounter = (PDWORD) (pPerfCounterBlock + 1);
|
||
|
||
#ifdef USE_IPHLPAPI
|
||
*pdwCounter = UdpStats.dwInDatagrams + UdpStats.dwOutDatagrams;
|
||
*++pdwCounter = UdpStats.dwInDatagrams;
|
||
*++pdwCounter = UdpStats.dwNoPorts;
|
||
*++pdwCounter = UdpStats.dwInErrors;
|
||
*++pdwCounter = UdpStats.dwOutDatagrams;
|
||
#else
|
||
*pdwCounter = UDP_COUNTER(UDP_INDATAGRAMS_INDEX) +
|
||
UDP_COUNTER(UDP_OUTDATAGRAMS_INDEX);
|
||
|
||
*++pdwCounter = UDP_COUNTER(UDP_INDATAGRAMS_INDEX);
|
||
*++pdwCounter = UDP_COUNTER(UDP_NOPORTS_INDEX);
|
||
*++pdwCounter = UDP_COUNTER(UDP_INERRORS_INDEX);
|
||
*++pdwCounter = UDP_COUNTER(UDP_OUTDATAGRAMS_INDEX);
|
||
#endif
|
||
// setup counters and pointers for next counter
|
||
|
||
NumObjectTypesTemp += 1;
|
||
lpDataTemp = (LPVOID)++pdwCounter;
|
||
// SpaceNeeded is kept up already
|
||
|
||
}
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
#ifdef USE_SNMP
|
||
|
||
// Get prepared for the next data collection
|
||
|
||
VariableBindings.list = VariableBindingsArray + OIDS_OFFSET;
|
||
VariableBindings.len = OIDS_LENGTH;
|
||
VariableBindingsICMP.list = VariableBindingsArray + ICMP_OIDS_OFFSET;
|
||
VariableBindingsICMP.len = ICMP_OIDS_LENGTH;
|
||
|
||
#else
|
||
HEAP_PROBE();
|
||
|
||
SnmpUtilVarBindListFree (&VariableBindings);
|
||
|
||
HEAP_PROBE();
|
||
|
||
#endif
|
||
#endif
|
||
} // endif SNMP Objects
|
||
|
||
// Set the returned values
|
||
|
||
*lppData = ALIGN_ON_QWORD((LPVOID) lpDataTemp);
|
||
*lpcbTotalBytes = QWORD_MULTIPLE(SpaceNeeded);
|
||
*lpNumObjectTypes = NumObjectTypesTemp;
|
||
|
||
HEAP_PROBE();
|
||
|
||
REPORT_SUCCESS (TCP_COLLECT_DATA, LOG_DEBUG);
|
||
return ERROR_SUCCESS;
|
||
} // CollectTcpIpPerformanceData
|
||
#pragma warning ( default : 4127)
|
||
|
||
DWORD
|
||
CloseTcpIpPerformanceData(
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine closes the open handles to TCP/IP devices.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
|
||
Return Value:
|
||
|
||
Win32 Status.
|
||
|
||
--*/
|
||
|
||
{
|
||
#ifndef USE_IPHLPAPI
|
||
int i;
|
||
#endif
|
||
|
||
REPORT_INFORMATION (TCP_ENTERING_CLOSE, LOG_VERBOSE);
|
||
|
||
if (dwTcpRefCount > 0) {
|
||
dwTcpRefCount--;
|
||
if (dwTcpRefCount == 0) {
|
||
// Close NBT
|
||
CloseNbtPerformanceData ();
|
||
|
||
|
||
#ifdef USE_DSIS
|
||
// Close DSIS
|
||
CloseDsisPerformanceData ();
|
||
#endif // USE_DSIS
|
||
|
||
/* This portion of the code for CloseTcpIpPerformanceData() could be used in
|
||
the CollectTcpIpPerformanceData() routine to close an open SNMP Manager
|
||
session.
|
||
|
||
So, name this portion of the code: B
|
||
|
||
*/
|
||
#ifdef USE_SNMP
|
||
if ( TcpIpSession != (LPSNMP_MGR_SESSION) NULL ) {
|
||
if ( ! SnmpMgrClose (TcpIpSession) ) {
|
||
REPORT_ERROR_DATA (TCP_SNMP_MGR_CLOSE, LOG_DEBUG,
|
||
GetLastError (), sizeof(DWORD));
|
||
}
|
||
|
||
TcpIpSession = (LPSNMP_MGR_SESSION) NULL;
|
||
} else {
|
||
REPORT_WARNING (TCP_NULL_SESSION, LOG_DEBUG);
|
||
}
|
||
|
||
/* End of code B
|
||
*/
|
||
#endif
|
||
|
||
HEAP_PROBE();
|
||
|
||
#ifndef USE_IPHLPAPI
|
||
for (i = 0; i < NO_OF_OIDS; i++) {
|
||
SnmpUtilOidFree ( &(RefNames[i]));
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
|
||
for (i = 0; i < NO_OF_IF_OIDS; i++) {
|
||
SnmpUtilOidFree (&(IFPermVariableBindingsArray[i].name));
|
||
}
|
||
|
||
HEAP_PROBE();
|
||
#else
|
||
if (IfTable) {
|
||
RtlFreeHeap(RtlProcessHeap(), 0L, IfTable);
|
||
IfTable = NULL;
|
||
}
|
||
#endif
|
||
|
||
#if 0
|
||
// this is closed by the INETMIB1 on process detach
|
||
// so we don't need to do it here.
|
||
|
||
// close event handle used by SNMP
|
||
if (CloseHandle (hSnmpEvent)) {
|
||
hSnmpEvent = NULL;
|
||
}
|
||
#endif
|
||
|
||
#ifdef LOAD_INETMIB1
|
||
|
||
FreeLibrary (hInetMibDll);
|
||
|
||
#endif
|
||
}
|
||
}
|
||
|
||
MonCloseEventLog();
|
||
|
||
return ERROR_SUCCESS;
|
||
|
||
} // CloseTcpIpPerformanceData
|