You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1755 lines
48 KiB
1755 lines
48 KiB
#include "allinc.h"
|
|
|
|
DWORD
|
|
LoadSystem()
|
|
{
|
|
DWORD dwResult;
|
|
|
|
TraceEnter("LoadSystem");
|
|
|
|
if(g_Cache.pRpcSysInfo)
|
|
{
|
|
if(g_Cache.pRpcSysInfo->aaSysObjectID.asnValue.object.ids)
|
|
{
|
|
SnmpUtilOidFree(&g_Cache.pRpcSysInfo->aaSysObjectID.asnValue.object);
|
|
}
|
|
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcSysInfo);
|
|
|
|
g_Cache.pRpcSysInfo = NULL;
|
|
}
|
|
|
|
dwResult = GetSysInfo(&(g_Cache.pRpcSysInfo),
|
|
g_hPrivateHeap,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetSysInfo failed with error %x",dwResult);
|
|
TraceLeave("LoadSysInfo");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
TraceLeave("LoadSysInfo");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
LoadIfTable()
|
|
{
|
|
DWORD dwResult;
|
|
|
|
TraceEnter("LoadIfTable");
|
|
|
|
if(g_Cache.pRpcIfTable)
|
|
{
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIfTable);
|
|
|
|
g_Cache.pRpcIfTable = NULL;
|
|
}
|
|
|
|
dwResult = InternalGetIfTable(&(g_Cache.pRpcIfTable),
|
|
g_hPrivateHeap,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetIfTable failed with error %x",
|
|
dwResult);
|
|
TraceLeave("LoadIfTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
TraceLeave("LoadIfTable");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadIpAddrTable()
|
|
{
|
|
DWORD dwResult;
|
|
|
|
TraceEnter("LoadIpAddrTable");
|
|
|
|
if(g_Cache.pRpcIpAddrTable)
|
|
{
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIpAddrTable);
|
|
|
|
g_Cache.pRpcIpAddrTable = NULL;
|
|
}
|
|
|
|
dwResult = InternalGetIpAddrTable(&(g_Cache.pRpcIpAddrTable),
|
|
g_hPrivateHeap,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetIpAddrTable failed with error %x",
|
|
dwResult);
|
|
TraceLeave("LoadIpAddrTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
TraceLeave("LoadIpAddrTable");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadIpNetTable()
|
|
{
|
|
DWORD dwResult;
|
|
|
|
TraceEnter("LoadIpNetTable");
|
|
|
|
if(g_Cache.pRpcIpNetTable)
|
|
{
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIpNetTable);
|
|
|
|
g_Cache.pRpcIpNetTable = NULL;
|
|
}
|
|
|
|
dwResult = InternalGetIpNetTable(&(g_Cache.pRpcIpNetTable),
|
|
g_hPrivateHeap,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetIpNetTable failed with error %x",
|
|
dwResult);
|
|
TraceLeave("LoadIpNetTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
TraceLeave("LoadIpNetTable");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadIpForwardTable()
|
|
{
|
|
DWORD dwResult;
|
|
|
|
TraceEnter("LoadIpForwardTable");
|
|
|
|
if(g_Cache.pRpcIpForwardTable)
|
|
{
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIpForwardTable);
|
|
|
|
g_Cache.pRpcIpForwardTable = NULL;
|
|
}
|
|
|
|
dwResult = InternalGetIpForwardTable(&(g_Cache.pRpcIpForwardTable),
|
|
g_hPrivateHeap,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetIpForwardTable failed with error %x",
|
|
dwResult);
|
|
TraceLeave("LoadIpForwardTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
TraceLeave("LoadIpForwardTable");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadTcpTable()
|
|
{
|
|
DWORD dwResult, i;
|
|
|
|
TraceEnter("LoadTcpTable");
|
|
|
|
if(g_Cache.pRpcTcpTable)
|
|
{
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcTcpTable);
|
|
|
|
g_Cache.pRpcTcpTable = NULL;
|
|
}
|
|
|
|
dwResult = InternalGetTcpTable(&(g_Cache.pRpcTcpTable),
|
|
g_hPrivateHeap,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetTcpTable failed with error %x",
|
|
dwResult);
|
|
TraceLeave("LoadTcpTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//
|
|
// modify port numbers to be in host byte order
|
|
//
|
|
|
|
for (i = 0; i < g_Cache.pRpcTcpTable->dwNumEntries; i++)
|
|
{
|
|
g_Cache.pRpcTcpTable->table[i].dwLocalPort =
|
|
(DWORD)ntohs((WORD)g_Cache.pRpcTcpTable->table[i].dwLocalPort);
|
|
g_Cache.pRpcTcpTable->table[i].dwRemotePort =
|
|
(DWORD)ntohs((WORD)g_Cache.pRpcTcpTable->table[i].dwRemotePort);
|
|
}
|
|
|
|
TraceLeave("LoadTcpTable");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadTcp6Table()
|
|
{
|
|
DWORD dwResult, i;
|
|
|
|
TraceEnter("LoadTcp6Table");
|
|
|
|
if(g_Cache.pRpcTcp6Table)
|
|
{
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcTcp6Table);
|
|
|
|
g_Cache.pRpcTcp6Table = NULL;
|
|
}
|
|
|
|
dwResult = AllocateAndGetTcpExTableFromStack(
|
|
(TCP_EX_TABLE **)&(g_Cache.pRpcTcp6Table),
|
|
TRUE, g_hPrivateHeap, 0, AF_INET6);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetTcp6Table failed with error %x",
|
|
dwResult);
|
|
TraceLeave("LoadTcp6Table");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//
|
|
// modify port numbers to be in host byte order
|
|
// and scope ids to be in network byte order
|
|
//
|
|
|
|
for (i = 0; i < g_Cache.pRpcTcp6Table->dwNumEntries; i++)
|
|
{
|
|
g_Cache.pRpcTcp6Table->table[i].tct_localport =
|
|
(DWORD)ntohs((WORD)g_Cache.pRpcTcp6Table->table[i].tct_localport);
|
|
g_Cache.pRpcTcp6Table->table[i].tct_remoteport =
|
|
(DWORD)ntohs((WORD)g_Cache.pRpcTcp6Table->table[i].tct_remoteport);
|
|
g_Cache.pRpcTcp6Table->table[i].tct_localscopeid =
|
|
htonl(g_Cache.pRpcTcp6Table->table[i].tct_localscopeid);
|
|
g_Cache.pRpcTcp6Table->table[i].tct_remotescopeid =
|
|
htonl(g_Cache.pRpcTcp6Table->table[i].tct_remotescopeid);
|
|
}
|
|
|
|
TraceLeave("LoadTcp6Table");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadUdpTable()
|
|
{
|
|
DWORD dwResult, i;
|
|
|
|
TraceEnter("LoadUdpTable");
|
|
|
|
if(g_Cache.pRpcUdpTable)
|
|
{
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcUdpTable);
|
|
|
|
g_Cache.pRpcUdpTable = NULL;
|
|
}
|
|
|
|
|
|
dwResult = InternalGetUdpTable(&(g_Cache.pRpcUdpTable),
|
|
g_hPrivateHeap,
|
|
0);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetUdpTable failed with error %x",
|
|
dwResult);
|
|
TraceLeave("LoadUdpTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//
|
|
// modify port numbers to be in host byte order
|
|
//
|
|
|
|
for (i = 0; i < g_Cache.pRpcUdpTable->dwNumEntries; i++)
|
|
{
|
|
g_Cache.pRpcUdpTable->table[i].dwLocalPort =
|
|
(DWORD)ntohs((WORD)g_Cache.pRpcUdpTable->table[i].dwLocalPort);
|
|
}
|
|
|
|
TraceLeave("LoadUdpTable");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadUdp6ListenerTable()
|
|
{
|
|
DWORD dwResult, i;
|
|
|
|
TraceEnter("LoadUdp6ListenerTable");
|
|
|
|
if(g_Cache.pRpcUdp6ListenerTable)
|
|
{
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcUdp6ListenerTable);
|
|
|
|
g_Cache.pRpcUdp6ListenerTable = NULL;
|
|
}
|
|
|
|
|
|
dwResult = AllocateAndGetUdpExTableFromStack(
|
|
(UDP_EX_TABLE **)&(g_Cache.pRpcUdp6ListenerTable),
|
|
TRUE, g_hPrivateHeap, 0, AF_INET6);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetUdp6ListenerTable failed with error %x",
|
|
dwResult);
|
|
TraceLeave("LoadUdp6ListenerTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//
|
|
// modify port numbers to be in host byte order
|
|
// and scope ids to be in network byte order
|
|
//
|
|
|
|
for (i = 0; i < g_Cache.pRpcUdp6ListenerTable->dwNumEntries; i++)
|
|
{
|
|
g_Cache.pRpcUdp6ListenerTable->table[i].ule_localport =
|
|
(DWORD)ntohs((WORD)g_Cache.pRpcUdp6ListenerTable->table[i].ule_localport);
|
|
g_Cache.pRpcUdp6ListenerTable->table[i].ule_localscopeid =
|
|
htonl(g_Cache.pRpcUdp6ListenerTable->table[i].ule_localscopeid);
|
|
}
|
|
|
|
TraceLeave("LoadUdp6ListenerTable");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
GetSysInfo(
|
|
MIB_SYSINFO **ppRpcSysInfo,
|
|
HANDLE hHeap,
|
|
DWORD dwAllocFlags
|
|
)
|
|
{
|
|
DWORD dwResult,dwValueType,dwValueLen;
|
|
PMIB_SYSINFO pRpcSysInfo;
|
|
HKEY hkeySysInfo;
|
|
DWORD dwBytes = 0, i, dwOidLen;
|
|
PCHAR pchBuff, pchStr, pchToken;
|
|
BOOL bOverride;
|
|
|
|
TraceEnter("GetSysInfo");
|
|
|
|
*ppRpcSysInfo = NULL;
|
|
|
|
pRpcSysInfo = HeapAlloc(hHeap,
|
|
dwAllocFlags,
|
|
sizeof(MIB_SYSINFO));
|
|
|
|
if(pRpcSysInfo is NULL)
|
|
{
|
|
dwResult = GetLastError();
|
|
|
|
TRACE1("Allocation failed with error %d",
|
|
dwResult);
|
|
TraceLeave("GetSysInfo");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
REG_KEY_MIB2,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkeySysInfo);
|
|
|
|
if (dwResult isnot NO_ERROR) {
|
|
|
|
HeapFree(hHeap,
|
|
dwAllocFlags,
|
|
pRpcSysInfo);
|
|
|
|
TRACE1("Couldnt open mib2 registry key. Error %d", dwResult);
|
|
TraceLeave("GetSysInfo");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->dwSysServices);
|
|
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("sysServices"),
|
|
0,
|
|
&dwValueType,
|
|
(LPBYTE)&pRpcSysInfo->dwSysServices,
|
|
&dwValueLen
|
|
);
|
|
|
|
if (dwResult isnot NO_ERROR) {
|
|
|
|
HeapFree(hHeap,
|
|
dwAllocFlags,
|
|
pRpcSysInfo);
|
|
|
|
TRACE1("Couldnt read sysServices value. Error %d", dwResult);
|
|
TraceLeave("GetSysInfo");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
bOverride = FALSE;
|
|
|
|
do
|
|
{
|
|
//
|
|
// First get the length of the OID
|
|
//
|
|
|
|
|
|
dwValueLen = 0;
|
|
|
|
dwResult = RegQueryValueExA(hkeySysInfo,
|
|
"sysObjectID",
|
|
0,
|
|
&dwValueType,
|
|
NULL,
|
|
&dwValueLen);
|
|
|
|
if(((dwResult isnot ERROR_MORE_DATA) and (dwResult isnot NO_ERROR)) or
|
|
(dwValueLen is 0))
|
|
{
|
|
//
|
|
// The only two codes that give us a good buffer len are
|
|
// NO_ERROR and ERROR_MORE_DATA. If the error code is not one
|
|
// of those, or if the oid len is 0, just set the OID to system oid
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
pchBuff = HeapAlloc(g_hPrivateHeap,
|
|
HEAP_ZERO_MEMORY,
|
|
dwValueLen + 1);
|
|
|
|
if(pchBuff is NULL)
|
|
{
|
|
break;
|
|
}
|
|
|
|
dwResult = RegQueryValueExA(hkeySysInfo,
|
|
"sysObjectID",
|
|
0,
|
|
&dwValueType,
|
|
pchBuff,
|
|
&dwValueLen);
|
|
|
|
if((dwResult isnot NO_ERROR) or
|
|
(dwValueType isnot REG_SZ) or
|
|
(dwValueLen is 0))
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Parse out the oid and store it away
|
|
// pchBuff is NULL terminated so we use strtok to overwrite
|
|
// all the "." with \0. This way we figure out the number
|
|
// of ids. Then we allocate memory to hold those many ids
|
|
//
|
|
|
|
dwOidLen = 1;
|
|
|
|
pchToken = strtok(pchBuff,".");
|
|
|
|
while(pchToken)
|
|
{
|
|
dwOidLen++;
|
|
|
|
pchToken = strtok(NULL,".");
|
|
}
|
|
|
|
//
|
|
// If the leading OID is 0, there is a problem
|
|
//
|
|
|
|
if(atoi(pchBuff) is 0)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pRpcSysInfo->aaSysObjectID.asnType = ASN_OBJECTIDENTIFIER;
|
|
|
|
pRpcSysInfo->aaSysObjectID.asnValue.object.idLength = dwOidLen;
|
|
|
|
pRpcSysInfo->aaSysObjectID.asnValue.object.ids =
|
|
SnmpUtilMemAlloc(dwOidLen * sizeof(UINT));
|
|
|
|
for(i = 0, pchStr = pchBuff; i < dwOidLen; i++)
|
|
{
|
|
pRpcSysInfo->aaSysObjectID.asnValue.object.ids[i] = atoi(pchStr);
|
|
|
|
pchStr += strlen(pchStr) + 1;
|
|
}
|
|
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
pchBuff);
|
|
|
|
bOverride = TRUE;
|
|
|
|
}while(FALSE);
|
|
|
|
if(!bOverride)
|
|
{
|
|
SnmpUtilOidCpy(&pRpcSysInfo->aaSysObjectID.asnValue.object,
|
|
SnmpSvcGetEnterpriseOID());
|
|
}
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysName);
|
|
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("sysName"),
|
|
0,
|
|
&dwValueType,
|
|
pRpcSysInfo->rgbySysName,
|
|
&dwValueLen
|
|
);
|
|
|
|
if (dwResult isnot NO_ERROR) {
|
|
|
|
TRACE1("Couldnt read sysName value. Error %d", dwResult);
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysName);
|
|
|
|
if (!GetComputerNameA(pRpcSysInfo->rgbySysName, &dwValueLen)) {
|
|
|
|
HeapFree(hHeap,
|
|
dwAllocFlags,
|
|
pRpcSysInfo);
|
|
|
|
dwResult = GetLastError();
|
|
|
|
TRACE1("Couldnt read computer name. Error %d", dwResult);
|
|
TraceLeave("GetSysInfo");
|
|
|
|
return dwResult;
|
|
}
|
|
}
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysContact);
|
|
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("sysContact"),
|
|
0,
|
|
&dwValueType,
|
|
pRpcSysInfo->rgbySysContact,
|
|
&dwValueLen
|
|
);
|
|
|
|
if (dwResult isnot NO_ERROR) {
|
|
pRpcSysInfo->rgbySysContact[0] = '\0';
|
|
}
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysLocation);
|
|
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("sysLocation"),
|
|
0,
|
|
&dwValueType,
|
|
pRpcSysInfo->rgbySysLocation,
|
|
&dwValueLen
|
|
);
|
|
|
|
if (dwResult isnot NO_ERROR)
|
|
{
|
|
pRpcSysInfo->rgbySysLocation[0] = '\0';
|
|
}
|
|
|
|
RegCloseKey(hkeySysInfo);
|
|
|
|
strcpy(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("Hardware: "));
|
|
dwBytes += strlen(TEXT("Hardware: "));
|
|
|
|
dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
REG_KEY_CPU,
|
|
0,
|
|
KEY_QUERY_VALUE |
|
|
KEY_ENUMERATE_SUB_KEYS,
|
|
&hkeySysInfo);
|
|
|
|
if (dwResult is NO_ERROR) {
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("Identifier"),
|
|
0,
|
|
&dwValueType,
|
|
&pRpcSysInfo->rgbySysDescr[dwBytes],
|
|
&dwValueLen);
|
|
|
|
if (dwResult is NO_ERROR) {
|
|
|
|
dwBytes += dwValueLen - 1;
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(" "));
|
|
|
|
} else {
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("CPU Unknown "));
|
|
dwBytes += strlen(TEXT("CPU Unknown "));
|
|
}
|
|
|
|
RegCloseKey(hkeySysInfo);
|
|
|
|
} else {
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("CPU Unknown "));
|
|
dwBytes += strlen(TEXT("CPU Unknown "));
|
|
}
|
|
|
|
dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
REG_KEY_SYSTEM,
|
|
0,
|
|
KEY_QUERY_VALUE |
|
|
KEY_ENUMERATE_SUB_KEYS,
|
|
&hkeySysInfo);
|
|
|
|
if (dwResult is NO_ERROR) {
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("Identifier"),
|
|
0,
|
|
&dwValueType,
|
|
&pRpcSysInfo->rgbySysDescr[dwBytes],
|
|
&dwValueLen);
|
|
|
|
if (dwResult is NO_ERROR) {
|
|
|
|
dwBytes += dwValueLen - 1;
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(" "));
|
|
|
|
} else {
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("SystemType Unknown "));
|
|
dwBytes += strlen(TEXT("SystemType Unknown "));
|
|
}
|
|
|
|
RegCloseKey(hkeySysInfo);
|
|
|
|
} else {
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("SystemType Unknown "));
|
|
dwBytes += strlen(TEXT("SystemType Unknown "));
|
|
}
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT_SOFTWARE_WINDOWS_VERSION);
|
|
dwBytes += strlen(TEXT_SOFTWARE_WINDOWS_VERSION);
|
|
|
|
dwResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
REG_KEY_VERSION,
|
|
0,
|
|
KEY_QUERY_VALUE |
|
|
KEY_ENUMERATE_SUB_KEYS,
|
|
&hkeySysInfo);
|
|
|
|
if (dwResult is NO_ERROR) {
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("CurrentVersion"),
|
|
0,
|
|
&dwValueType,
|
|
&pRpcSysInfo->rgbySysDescr[dwBytes],
|
|
&dwValueLen);
|
|
|
|
if (dwResult is NO_ERROR) {
|
|
|
|
dwBytes += dwValueLen - 1;
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(" "));
|
|
|
|
} else {
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("Unknown "));
|
|
dwBytes += strlen(TEXT("Unknown "));
|
|
}
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("(Build "));
|
|
dwBytes += strlen(TEXT("(Build "));
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
|
|
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("CurrentBuildNumber"),
|
|
0,
|
|
&dwValueType,
|
|
&pRpcSysInfo->rgbySysDescr[dwBytes],
|
|
&dwValueLen);
|
|
|
|
if (dwResult is NO_ERROR) {
|
|
|
|
dwBytes += dwValueLen - 1;
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(" "));
|
|
|
|
} else {
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("Unknown "));
|
|
dwBytes += strlen(TEXT("Unknown "));
|
|
}
|
|
|
|
dwValueLen = sizeof(pRpcSysInfo->rgbySysDescr) - dwBytes;
|
|
|
|
dwResult = RegQueryValueEx(hkeySysInfo,
|
|
TEXT("CurrentType"),
|
|
0,
|
|
&dwValueType,
|
|
&pRpcSysInfo->rgbySysDescr[dwBytes],
|
|
&dwValueLen);
|
|
|
|
if (dwResult is NO_ERROR) {
|
|
|
|
dwBytes += dwValueLen - 1;
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes++], TEXT(")"));
|
|
|
|
} else {
|
|
|
|
pRpcSysInfo->rgbySysDescr[dwBytes - 1] = ')';
|
|
}
|
|
|
|
RegCloseKey(hkeySysInfo);
|
|
|
|
} else {
|
|
|
|
strcat(&pRpcSysInfo->rgbySysDescr[dwBytes], TEXT("Unknown"));
|
|
dwBytes += strlen(TEXT("Unknown"));
|
|
}
|
|
|
|
*ppRpcSysInfo = pRpcSysInfo;
|
|
|
|
TraceLeave("GetSysInfo");
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
FreeIpv6IfTable()
|
|
{
|
|
if (g_Cache.pRpcIpv6IfTable.table) {
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIpv6IfTable.table);
|
|
|
|
g_Cache.pRpcIpv6IfTable.table = NULL;
|
|
g_Cache.pRpcIpv6IfTable.dwNumEntries = 0;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeIpv6AddrTable()
|
|
{
|
|
if (g_Cache.pRpcIpv6AddrTable.table) {
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIpv6AddrTable.table);
|
|
|
|
g_Cache.pRpcIpv6AddrTable.table = NULL;
|
|
g_Cache.pRpcIpv6AddrTable.dwNumEntries = 0;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeIpv6NetToMediaTable()
|
|
{
|
|
if (g_Cache.pRpcIpv6NetToMediaTable.table) {
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIpv6NetToMediaTable.table);
|
|
|
|
g_Cache.pRpcIpv6NetToMediaTable.table = NULL;
|
|
g_Cache.pRpcIpv6NetToMediaTable.dwNumEntries = 0;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeInetIcmpTable()
|
|
{
|
|
if (g_Cache.pRpcInetIcmpTable.table) {
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcInetIcmpTable.table);
|
|
|
|
g_Cache.pRpcInetIcmpTable.table = NULL;
|
|
g_Cache.pRpcInetIcmpTable.dwNumEntries = 0;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeInetIcmpMsgTable()
|
|
{
|
|
if (g_Cache.pRpcInetIcmpMsgTable.table) {
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcInetIcmpMsgTable.table);
|
|
|
|
g_Cache.pRpcInetIcmpMsgTable.table = NULL;
|
|
g_Cache.pRpcInetIcmpMsgTable.dwNumEntries = 0;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FreeIpv6RouteTable()
|
|
{
|
|
if (g_Cache.pRpcIpv6RouteTable.table) {
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIpv6RouteTable.table);
|
|
|
|
g_Cache.pRpcIpv6RouteTable.table = NULL;
|
|
g_Cache.pRpcIpv6RouteTable.dwNumEntries = 0;
|
|
}
|
|
|
|
if (g_Cache.pRpcIpv6AddrPrefixTable.table) {
|
|
HeapFree(g_hPrivateHeap,
|
|
0,
|
|
g_Cache.pRpcIpv6AddrPrefixTable.table);
|
|
|
|
g_Cache.pRpcIpv6AddrPrefixTable.table = NULL;
|
|
g_Cache.pRpcIpv6AddrPrefixTable.dwNumEntries = 0;
|
|
}
|
|
}
|
|
|
|
typedef enum {
|
|
Preferred = 1,
|
|
Deprecated,
|
|
Invalid,
|
|
Inaccessible,
|
|
Unknown
|
|
}MIB_ADDR_STATUS;
|
|
|
|
//
|
|
// This array gives the MIB state we report for each internal
|
|
// address state.
|
|
//
|
|
DWORD
|
|
MibAddrState[] = {
|
|
Invalid, // DAD_STATE_INVALID
|
|
Unknown, // DAD_STATE_TENTATIVE
|
|
Unknown, // DAD_STATE_DUPLICATE
|
|
Deprecated, // DAD_STATE_DEPRECATED
|
|
Preferred // DAD_STATE_PREFERRED
|
|
};
|
|
|
|
int
|
|
__cdecl
|
|
CompareIpv6IfRow(
|
|
CONST VOID *pvElem1,
|
|
CONST VOID *pvElem2
|
|
)
|
|
{
|
|
LONG lResult;
|
|
PMIB_IPV6_IF pRow1 = (PMIB_IPV6_IF)pvElem1;
|
|
PMIB_IPV6_IF pRow2 = (PMIB_IPV6_IF)pvElem2;
|
|
|
|
return Cmp(pRow1->dwIndex, pRow2->dwIndex, lResult);
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
CompareInetIcmpRow(
|
|
CONST VOID *pvElem1,
|
|
CONST VOID *pvElem2
|
|
)
|
|
{
|
|
LONG lResult;
|
|
PMIB_INET_ICMP pRow1 = (PMIB_INET_ICMP)pvElem1;
|
|
PMIB_INET_ICMP pRow2 = (PMIB_INET_ICMP)pvElem2;
|
|
|
|
if(Cmp(pRow1->dwAFType,
|
|
pRow2->dwAFType,
|
|
lResult) isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
return Cmp(pRow1->dwIfIndex, pRow2->dwIfIndex, lResult);
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
CompareInetIcmpMsgRow(
|
|
CONST VOID *pvElem1,
|
|
CONST VOID *pvElem2
|
|
)
|
|
{
|
|
LONG lResult;
|
|
PMIB_INET_ICMP_MSG pRow1 = (PMIB_INET_ICMP_MSG)pvElem1;
|
|
PMIB_INET_ICMP_MSG pRow2 = (PMIB_INET_ICMP_MSG)pvElem2;
|
|
|
|
if(Cmp(pRow1->dwAFType,
|
|
pRow2->dwAFType,
|
|
lResult) isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
if(Cmp(pRow1->dwIfIndex,
|
|
pRow2->dwIfIndex,
|
|
lResult) isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
if(Cmp(pRow1->dwType,
|
|
pRow2->dwType,
|
|
lResult) isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
return Cmp(pRow1->dwCode, pRow2->dwCode, lResult);
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
CompareIpv6AddrRow(
|
|
CONST VOID *pvElem1,
|
|
CONST VOID *pvElem2
|
|
)
|
|
{
|
|
LONG lResult;
|
|
PMIB_IPV6_ADDR pRow1 = (PMIB_IPV6_ADDR)pvElem1;
|
|
PMIB_IPV6_ADDR pRow2 = (PMIB_IPV6_ADDR)pvElem2;
|
|
|
|
if(Cmp(pRow1->dwIfIndex,
|
|
pRow2->dwIfIndex,
|
|
lResult) isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
return memcmp(&pRow1->ipAddress,
|
|
&pRow2->ipAddress,
|
|
sizeof(IN6_ADDR));
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
CompareIpv6NetToMediaRow(
|
|
CONST VOID *pvElem1,
|
|
CONST VOID *pvElem2
|
|
)
|
|
{
|
|
LONG lResult;
|
|
PMIB_IPV6_NET_TO_MEDIA pRow1 = (PMIB_IPV6_NET_TO_MEDIA)pvElem1;
|
|
PMIB_IPV6_NET_TO_MEDIA pRow2 = (PMIB_IPV6_NET_TO_MEDIA)pvElem2;
|
|
|
|
if(Cmp(pRow1->dwIfIndex,
|
|
pRow2->dwIfIndex,
|
|
lResult) isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
return memcmp(&pRow1->ipAddress,
|
|
&pRow2->ipAddress,
|
|
sizeof(IN6_ADDR));
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
CompareIpv6RouteRow(
|
|
CONST VOID *pvElem1,
|
|
CONST VOID *pvElem2
|
|
)
|
|
{
|
|
LONG lResult;
|
|
PMIB_IPV6_ROUTE pRow1 = (PMIB_IPV6_ROUTE)pvElem1;
|
|
PMIB_IPV6_ROUTE pRow2 = (PMIB_IPV6_ROUTE)pvElem2;
|
|
|
|
lResult = memcmp(&pRow1->ipPrefix,
|
|
&pRow2->ipPrefix,
|
|
sizeof(IN6_ADDR));
|
|
if (lResult isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
if(Cmp(pRow1->dwPrefixLength,
|
|
pRow2->dwPrefixLength,
|
|
lResult) isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
return Cmp(pRow1->dwIndex,
|
|
pRow2->dwIndex,
|
|
lResult);
|
|
}
|
|
|
|
int
|
|
__cdecl
|
|
CompareIpv6AddrPrefixRow(
|
|
CONST VOID *pvElem1,
|
|
CONST VOID *pvElem2
|
|
)
|
|
{
|
|
LONG lResult;
|
|
PMIB_IPV6_ADDR_PREFIX pRow1 = (PMIB_IPV6_ADDR_PREFIX)pvElem1;
|
|
PMIB_IPV6_ADDR_PREFIX pRow2 = (PMIB_IPV6_ADDR_PREFIX)pvElem2;
|
|
|
|
if(Cmp(pRow1->dwIfIndex,
|
|
pRow2->dwIfIndex,
|
|
lResult) isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
lResult = memcmp(&pRow1->ipPrefix,
|
|
&pRow2->ipPrefix,
|
|
sizeof(IN6_ADDR));
|
|
if (lResult isnot 0)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
return Cmp(pRow1->dwPrefixLength,
|
|
pRow2->dwPrefixLength,
|
|
lResult);
|
|
}
|
|
|
|
DWORD
|
|
LoadIpv6IfTable()
|
|
{
|
|
DWORD dwResult, dwOutBufLen = 0;
|
|
DWORD dwIfCount, dwAddrCount, i;
|
|
PIP_ADAPTER_ADDRESSES pFirstIf, pIf;
|
|
PIP_ADAPTER_UNICAST_ADDRESS pUni;
|
|
PIP_ADAPTER_ANYCAST_ADDRESS pAny;
|
|
PMIB_IPV6_ADDR pAddr;
|
|
PMIB_IPV6_IF pMibIf;
|
|
|
|
TraceEnter("LoadIpv6IfTable");
|
|
|
|
FreeIpv6IfTable();
|
|
FreeIpv6AddrTable();
|
|
|
|
dwResult = GetAdaptersAddresses(AF_INET6,
|
|
GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
|
|
NULL, NULL, &dwOutBufLen);
|
|
if (dwResult == ERROR_NO_DATA) {
|
|
return NO_ERROR;
|
|
}
|
|
|
|
pFirstIf = HeapAlloc(g_hPrivateHeap, 0, dwOutBufLen);
|
|
if(pFirstIf == NULL)
|
|
{
|
|
TraceLeave("LoadIpv6IfTable");
|
|
return GetLastError();
|
|
}
|
|
|
|
dwResult = GetAdaptersAddresses(AF_INET6,
|
|
GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
|
|
NULL, pFirstIf, &dwOutBufLen);
|
|
|
|
if(dwResult isnot NO_ERROR)
|
|
{
|
|
TRACE1("GetIpv6IfTable failed with error %x",
|
|
dwResult);
|
|
goto Cleanup;
|
|
}
|
|
dwAddrCount = dwIfCount = 0;
|
|
for (pIf=pFirstIf; pIf; pIf=pIf->Next) {
|
|
dwIfCount++;
|
|
for (pUni=pIf->FirstUnicastAddress; pUni; pUni=pUni->Next) {
|
|
dwAddrCount++;
|
|
}
|
|
for (pAny=pIf->FirstAnycastAddress; pAny; pAny=pAny->Next) {
|
|
dwAddrCount++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create the interface table
|
|
//
|
|
g_Cache.pRpcIpv6IfTable.table = HeapAlloc(g_hPrivateHeap, 0, dwIfCount * sizeof(MIB_IPV6_IF));
|
|
if (!g_Cache.pRpcIpv6IfTable.table) {
|
|
TraceLeave("LoadIpv6IfTable");
|
|
dwResult = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
for (pIf=pFirstIf; pIf; pIf=pIf->Next) {
|
|
i = g_Cache.pRpcIpv6IfTable.dwNumEntries++;
|
|
pMibIf = &g_Cache.pRpcIpv6IfTable.table[i];
|
|
pMibIf->dwIndex = pIf->Ipv6IfIndex;
|
|
pMibIf->dwEffectiveMtu = pIf->Mtu;
|
|
pMibIf->dwReasmMaxSize = 65535;
|
|
pMibIf->dwAdminStatus = 1; /* up */
|
|
pMibIf->dwOperStatus = pIf->OperStatus;
|
|
pMibIf->dwLastChange = 0;
|
|
pMibIf->dwPhysicalAddressLength = pIf->PhysicalAddressLength;
|
|
memcpy(pMibIf->bPhysicalAddress, pIf->PhysicalAddress,
|
|
pIf->PhysicalAddressLength);
|
|
wcscpy(pMibIf->wszDescription, pIf->Description);
|
|
}
|
|
qsort(g_Cache.pRpcIpv6IfTable.table,
|
|
dwIfCount,
|
|
sizeof(MIB_IPV6_IF),
|
|
CompareIpv6IfRow);
|
|
|
|
//
|
|
// Create the address table
|
|
//
|
|
g_Cache.pRpcIpv6AddrTable.table = HeapAlloc(g_hPrivateHeap, 0, dwAddrCount * sizeof(MIB_IPV6_ADDR));
|
|
if (!g_Cache.pRpcIpv6AddrTable.table) {
|
|
dwResult = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
for (pIf=pFirstIf; pIf; pIf=pIf->Next) {
|
|
for (pUni=pIf->FirstUnicastAddress; pUni; pUni=pUni->Next) {
|
|
i = g_Cache.pRpcIpv6AddrTable.dwNumEntries++;
|
|
pAddr = &g_Cache.pRpcIpv6AddrTable.table[i];
|
|
pAddr->dwIfIndex = pIf->Ipv6IfIndex;
|
|
pAddr->ipAddress = ((LPSOCKADDR_IN6)pUni->Address.lpSockaddr)->sin6_addr;
|
|
pAddr->dwPrefixLength = 64;
|
|
pAddr->dwType = 1;
|
|
pAddr->dwAnycastFlag = 2;
|
|
pAddr->dwStatus = (pIf->OperStatus == IfOperStatusUp)
|
|
? MibAddrState[pUni->DadState]
|
|
: Inaccessible;
|
|
}
|
|
for (pAny=pIf->FirstAnycastAddress; pAny; pAny=pAny->Next) {
|
|
i = g_Cache.pRpcIpv6AddrTable.dwNumEntries++;
|
|
pAddr = &g_Cache.pRpcIpv6AddrTable.table[i];
|
|
pAddr->dwIfIndex = pIf->Ipv6IfIndex;
|
|
pAddr->ipAddress = ((LPSOCKADDR_IN6)pAny->Address.lpSockaddr)->sin6_addr;
|
|
pAddr->dwPrefixLength = 64;
|
|
pAddr->dwType = 1;
|
|
pAddr->dwAnycastFlag = 1;
|
|
pAddr->dwStatus = 1;
|
|
}
|
|
}
|
|
qsort(g_Cache.pRpcIpv6AddrTable.table,
|
|
dwAddrCount,
|
|
sizeof(MIB_IPV6_ADDR),
|
|
CompareIpv6AddrRow);
|
|
|
|
Cleanup:
|
|
HeapFree(g_hPrivateHeap, 0, pFirstIf);
|
|
|
|
TraceLeave("LoadIpv6IfTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
//
|
|
// This array gives the ICMP message type value for each field
|
|
// in the ICMPStats structure (in ipinfo.h) and MIBICMPSTATS
|
|
// structure (in iprtrmib.h), which are identical. A value of
|
|
// -1 means that the field does not count messages for a specific
|
|
// type value.
|
|
//
|
|
DWORD
|
|
Ipv4IcmpFieldMsg[] = {
|
|
-1, // dwMsgs
|
|
-1, // dwErrors
|
|
3, // dwDestUnreachs
|
|
11, // dwTimeExcds
|
|
12, // dwParmProbs
|
|
4, // dwSrcQuenchs
|
|
5, // dwRedirects
|
|
8, // dwEchos
|
|
0, // dwEchoReps
|
|
13, // dwTimestamps
|
|
14, // dwTimestampReps
|
|
17, // dwAddrMasks
|
|
18, // dwAddrMaskReps
|
|
};
|
|
|
|
DWORD
|
|
LoadInetIcmpTable()
|
|
{
|
|
PMIB_INET_ICMP pRow;
|
|
PMIB_INET_ICMP_MSG pMsg;
|
|
MIB_ICMP Icmp4;
|
|
ICMPv6SNMPInfo Icmp6;
|
|
DWORD dwResult4, dwResult6, dwResult = NO_ERROR;
|
|
DWORD i, j, k, dwRowCount = 0, dwMsgCount = 0;
|
|
|
|
TraceEnter("LoadInetIcmpTable");
|
|
|
|
FreeInetIcmpTable();
|
|
FreeInetIcmpMsgTable();
|
|
|
|
dwResult4 = GetIcmpStatistics(&Icmp4);
|
|
if (dwResult4 == NO_ERROR) {
|
|
dwRowCount++;
|
|
|
|
for (j=0; j<sizeof(MIBICMPSTATS)/sizeof(DWORD); j++) {
|
|
if (Ipv4IcmpFieldMsg[j] == -1) {
|
|
continue;
|
|
}
|
|
if ((((DWORD*)&Icmp4.stats.icmpInStats)[j] > 0) ||
|
|
(((DWORD*)&Icmp4.stats.icmpOutStats)[j] > 0)) {
|
|
dwMsgCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
dwResult6 = GetIcmpStatsFromStackEx((PVOID)&Icmp6, AF_INET6);
|
|
if (dwResult6 == NO_ERROR) {
|
|
dwRowCount++;
|
|
|
|
for (k=0; k<256; k++) {
|
|
if ((Icmp6.icsi_instats.icmps_typecount[k] > 0) ||
|
|
(Icmp6.icsi_outstats.icmps_typecount[k] > 0)) {
|
|
dwMsgCount++;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Create the ICMP table
|
|
//
|
|
g_Cache.pRpcInetIcmpTable.table = HeapAlloc(g_hPrivateHeap, 0,
|
|
dwRowCount * sizeof(MIB_INET_ICMP));
|
|
if (!g_Cache.pRpcInetIcmpTable.table) {
|
|
TraceLeave("LoadInetIcmpTable");
|
|
dwResult = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
if (dwResult4 == NO_ERROR) {
|
|
i = g_Cache.pRpcInetIcmpTable.dwNumEntries++;
|
|
pRow = &g_Cache.pRpcInetIcmpTable.table[i];
|
|
pRow->dwAFType = 1; // IPv4
|
|
pRow->dwIfIndex = 0; // global
|
|
pRow->dwInMsgs = Icmp4.stats.icmpInStats.dwMsgs;
|
|
pRow->dwInErrors = Icmp4.stats.icmpInStats.dwErrors;
|
|
pRow->dwOutMsgs = Icmp4.stats.icmpOutStats.dwMsgs;
|
|
pRow->dwOutErrors = Icmp4.stats.icmpOutStats.dwErrors;
|
|
}
|
|
if (dwResult6 == NO_ERROR) {
|
|
i = g_Cache.pRpcInetIcmpTable.dwNumEntries++;
|
|
pRow = &g_Cache.pRpcInetIcmpTable.table[i];
|
|
pRow->dwAFType = 2; // IPv6
|
|
pRow->dwIfIndex = 0; // global
|
|
pRow->dwInMsgs = Icmp6.icsi_instats.icmps_msgs;
|
|
pRow->dwInErrors = Icmp6.icsi_instats.icmps_errors;
|
|
pRow->dwOutMsgs = Icmp6.icsi_outstats.icmps_msgs;
|
|
pRow->dwOutErrors = Icmp6.icsi_outstats.icmps_errors;
|
|
}
|
|
qsort(g_Cache.pRpcInetIcmpTable.table,
|
|
dwRowCount,
|
|
sizeof(MIB_INET_ICMP),
|
|
CompareInetIcmpRow);
|
|
|
|
//
|
|
// Create the ICMP message table
|
|
//
|
|
g_Cache.pRpcInetIcmpMsgTable.table = HeapAlloc(g_hPrivateHeap, 0,
|
|
dwMsgCount * sizeof(MIB_INET_ICMP_MSG));
|
|
if (!g_Cache.pRpcInetIcmpMsgTable.table) {
|
|
dwResult = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
if (dwResult4 == NO_ERROR) {
|
|
for (j=0; j<sizeof(MIBICMPSTATS)/sizeof(DWORD); j++) {
|
|
k = Ipv4IcmpFieldMsg[j];
|
|
if (k == -1) {
|
|
continue;
|
|
}
|
|
if ((((DWORD*)&Icmp4.stats.icmpInStats)[j] > 0) ||
|
|
(((DWORD*)&Icmp4.stats.icmpOutStats)[j] > 0)) {
|
|
|
|
i = g_Cache.pRpcInetIcmpMsgTable.dwNumEntries++;
|
|
pMsg = &g_Cache.pRpcInetIcmpMsgTable.table[i];
|
|
pMsg->dwAFType = 1; // IPv4
|
|
pMsg->dwIfIndex = 0; // global
|
|
pMsg->dwType = k;
|
|
pMsg->dwCode = 256; // all codes combined
|
|
pMsg->dwInPkts = ((DWORD*)&Icmp4.stats.icmpInStats)[j];
|
|
pMsg->dwOutPkts = ((DWORD*)&Icmp4.stats.icmpOutStats)[j];
|
|
}
|
|
}
|
|
}
|
|
if (dwResult6 == NO_ERROR) {
|
|
for (k=0; k<256; k++) {
|
|
if ((Icmp6.icsi_instats.icmps_typecount[k] > 0) ||
|
|
(Icmp6.icsi_outstats.icmps_typecount[k] > 0)) {
|
|
|
|
i = g_Cache.pRpcInetIcmpMsgTable.dwNumEntries++;
|
|
pMsg = &g_Cache.pRpcInetIcmpMsgTable.table[i];
|
|
pMsg->dwAFType = 2; // IPv6
|
|
pMsg->dwIfIndex = 0; // global
|
|
pMsg->dwType = k;
|
|
pMsg->dwCode = 256; // all codes combined
|
|
pMsg->dwInPkts = Icmp6.icsi_instats.icmps_typecount[k];
|
|
pMsg->dwOutPkts = Icmp6.icsi_outstats.icmps_typecount[k];
|
|
}
|
|
}
|
|
}
|
|
qsort(g_Cache.pRpcInetIcmpMsgTable.table,
|
|
dwMsgCount,
|
|
sizeof(MIB_INET_ICMP_MSG),
|
|
CompareInetIcmpMsgRow);
|
|
|
|
Cleanup:
|
|
TraceLeave("LoadInetIcmpTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
HANDLE g_hIpv6Handle = INVALID_HANDLE_VALUE;
|
|
|
|
VOID
|
|
OpenIpv6()
|
|
{
|
|
g_hIpv6Handle = CreateFileW(WIN_IPV6_DEVICE_NAME,
|
|
0,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
NULL, // security attributes
|
|
OPEN_EXISTING,
|
|
0, // flags & attributes
|
|
NULL); // template file
|
|
}
|
|
|
|
DWORD
|
|
CountNeighbors(
|
|
IN IPV6_INFO_INTERFACE *IF,
|
|
IN PVOID Arg)
|
|
{
|
|
BYTE bNceBuffer[sizeof(IPV6_INFO_NEIGHBOR_CACHE) + MAX_LINK_LAYER_ADDRESS_LENGTH];
|
|
IPV6_INFO_NEIGHBOR_CACHE *NCE = (IPV6_INFO_NEIGHBOR_CACHE *)bNceBuffer;
|
|
IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery;
|
|
DWORD dwInfoSize, dwBytesReturned;
|
|
DWORD *pdwCount = (DWORD*)Arg;
|
|
|
|
NextQuery.IF = IF->This;
|
|
NextQuery.Address = in6addr_any;
|
|
for (;;) {
|
|
Query = NextQuery;
|
|
dwInfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
|
|
|
|
if (!DeviceIoControl(g_hIpv6Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
|
|
&Query, sizeof Query,
|
|
NCE, dwInfoSize, &dwBytesReturned, NULL)) {
|
|
return GetLastError();
|
|
}
|
|
|
|
NextQuery = NCE->Query;
|
|
|
|
if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
|
|
(*pdwCount)++;
|
|
}
|
|
|
|
if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any))
|
|
break;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
typedef enum {
|
|
NtmsReachable = 1,
|
|
NtmsStale,
|
|
NtmsDelay,
|
|
NtmsProbe,
|
|
NtmsInvalid,
|
|
NtmsUnknown
|
|
}NET_TO_MEDIA_STATE;
|
|
|
|
DWORD
|
|
NDToMibState[] = {
|
|
NtmsStale, NtmsProbe, NtmsDelay, NtmsStale, NtmsReachable, NtmsReachable
|
|
};
|
|
|
|
typedef enum {
|
|
NtmtOther = 1,
|
|
NtmtDynamic,
|
|
NtmtStatic,
|
|
NtmtLocal
|
|
}NET_TO_MEDIA_TYPE;
|
|
|
|
DWORD
|
|
LoadNeighbors(
|
|
IN IPV6_INFO_INTERFACE *IF,
|
|
IN PVOID Arg)
|
|
{
|
|
BYTE bNceBuffer[sizeof(IPV6_INFO_NEIGHBOR_CACHE) + MAX_LINK_LAYER_ADDRESS_LENGTH];
|
|
IPV6_INFO_NEIGHBOR_CACHE *NCE = (IPV6_INFO_NEIGHBOR_CACHE *)bNceBuffer;
|
|
IPV6_QUERY_NEIGHBOR_CACHE Query, NextQuery;
|
|
DWORD dwInfoSize, dwBytesReturned, i;
|
|
PMIB_IPV6_NET_TO_MEDIA pRow;
|
|
DWORD *pdwCount = (DWORD*)Arg;
|
|
|
|
NextQuery.IF = IF->This;
|
|
NextQuery.Address = in6addr_any;
|
|
for (;;) {
|
|
Query = NextQuery;
|
|
dwInfoSize = sizeof *NCE + MAX_LINK_LAYER_ADDRESS_LENGTH;
|
|
|
|
if (!DeviceIoControl(g_hIpv6Handle, IOCTL_IPV6_QUERY_NEIGHBOR_CACHE,
|
|
&Query, sizeof Query,
|
|
NCE, dwInfoSize, &dwBytesReturned, NULL)) {
|
|
return GetLastError();
|
|
}
|
|
|
|
NextQuery = NCE->Query;
|
|
|
|
if (!IN6_ADDR_EQUAL(&Query.Address, &in6addr_any)) {
|
|
i = g_Cache.pRpcIpv6NetToMediaTable.dwNumEntries++;
|
|
pRow = &g_Cache.pRpcIpv6NetToMediaTable.table[i];
|
|
pRow->dwIfIndex = Query.IF.Index;
|
|
pRow->ipAddress = Query.Address;
|
|
memcpy(pRow->bPhysAddress, NCE+1, NCE->LinkLayerAddressLength);
|
|
pRow->dwPhysAddressLen = NCE->LinkLayerAddressLength;
|
|
if (pRow->dwState == ND_STATE_PERMANENT) {
|
|
pRow->dwType = NtmtStatic;
|
|
} else {
|
|
pRow->dwType = NtmtDynamic;
|
|
}
|
|
pRow->dwState = NDToMibState[NCE->NDState];
|
|
pRow->dwLastUpdated = 0;
|
|
pRow->dwValid = 1;
|
|
|
|
if (g_Cache.pRpcIpv6NetToMediaTable.dwNumEntries == *pdwCount)
|
|
break;
|
|
}
|
|
|
|
if (IN6_ADDR_EQUAL(&NextQuery.Address, &in6addr_any))
|
|
break;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
ForEachInterface(
|
|
IN DWORD (*func)(IPV6_INFO_INTERFACE *, PVOID),
|
|
IN PVOID arg)
|
|
{
|
|
IPV6_QUERY_INTERFACE Query;
|
|
IPV6_INFO_INTERFACE *IF;
|
|
DWORD InfoSize, BytesReturned, dwResult = NO_ERROR;
|
|
|
|
InfoSize = sizeof *IF + 2 * MAX_LINK_LAYER_ADDRESS_LENGTH;
|
|
IF = (IPV6_INFO_INTERFACE *) HeapAlloc(g_hPrivateHeap, 0, InfoSize);
|
|
if (IF == NULL) {
|
|
return GetLastError();
|
|
}
|
|
|
|
Query.Index = (u_int) -1;
|
|
|
|
for (;;) {
|
|
if (!DeviceIoControl(g_hIpv6Handle, IOCTL_IPV6_QUERY_INTERFACE,
|
|
&Query, sizeof Query,
|
|
IF, InfoSize, &BytesReturned,
|
|
NULL)) {
|
|
dwResult = GetLastError();
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (Query.Index != (u_int) -1) {
|
|
|
|
if ((BytesReturned < sizeof *IF) ||
|
|
(IF->Length < sizeof *IF) ||
|
|
(BytesReturned != IF->Length +
|
|
((IF->LocalLinkLayerAddress != 0) ?
|
|
IF->LinkLayerAddressLength : 0) +
|
|
((IF->RemoteLinkLayerAddress != 0) ?
|
|
IF->LinkLayerAddressLength : 0))) {
|
|
|
|
goto Cleanup;
|
|
}
|
|
|
|
dwResult = (*func)(IF, arg);
|
|
if (dwResult != NO_ERROR) {
|
|
return dwResult;
|
|
}
|
|
}
|
|
|
|
if (IF->Next.Index == (u_int) -1)
|
|
break;
|
|
Query = IF->Next;
|
|
}
|
|
|
|
Cleanup:
|
|
HeapFree(g_hPrivateHeap, 0, IF);
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
ForEachRoute(
|
|
IN DWORD (*func)(IPV6_INFO_ROUTE_TABLE *, PVOID, PVOID),
|
|
IN PVOID Arg1,
|
|
IN PVOID Arg2)
|
|
{
|
|
IPV6_QUERY_ROUTE_TABLE Query, NextQuery;
|
|
IPV6_INFO_ROUTE_TABLE RTE;
|
|
DWORD BytesReturned;
|
|
|
|
NextQuery.Neighbor.IF.Index = 0;
|
|
|
|
for (;;) {
|
|
Query = NextQuery;
|
|
|
|
if (!DeviceIoControl(g_hIpv6Handle, IOCTL_IPV6_QUERY_ROUTE_TABLE,
|
|
&Query, sizeof Query,
|
|
&RTE, sizeof RTE, &BytesReturned,
|
|
NULL)) {
|
|
return GetLastError();
|
|
}
|
|
|
|
NextQuery = RTE.Next;
|
|
|
|
if (Query.Neighbor.IF.Index != 0) {
|
|
|
|
RTE.This = Query;
|
|
(*func)(&RTE, Arg1, Arg2);
|
|
}
|
|
|
|
if (NextQuery.Neighbor.IF.Index == 0)
|
|
break;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadIpv6NetToMediaTable()
|
|
{
|
|
DWORD dwResult, dwOutBufLen = 0;
|
|
DWORD dwCount, i;
|
|
|
|
TraceEnter("LoadIpv6NetToMediaTable");
|
|
|
|
FreeIpv6NetToMediaTable();
|
|
|
|
OpenIpv6();
|
|
|
|
//
|
|
// Count entries
|
|
//
|
|
dwCount = 0;
|
|
ForEachInterface(CountNeighbors, &dwCount);
|
|
|
|
//
|
|
// Create the neighbor table
|
|
//
|
|
g_Cache.pRpcIpv6NetToMediaTable.table = HeapAlloc(g_hPrivateHeap, 0, dwCount * sizeof(MIB_IPV6_NET_TO_MEDIA));
|
|
if (!g_Cache.pRpcIpv6NetToMediaTable.table) {
|
|
TraceLeave("LoadIpv6NetToMediaTable");
|
|
return GetLastError();
|
|
}
|
|
|
|
//
|
|
// Load entries
|
|
//
|
|
dwResult = ForEachInterface(LoadNeighbors, &dwCount);
|
|
|
|
qsort(g_Cache.pRpcIpv6NetToMediaTable.table,
|
|
g_Cache.pRpcIpv6NetToMediaTable.dwNumEntries,
|
|
sizeof(MIB_IPV6_NET_TO_MEDIA),
|
|
CompareIpv6NetToMediaRow);
|
|
|
|
CloseHandle(g_hIpv6Handle);
|
|
|
|
TraceLeave("LoadIpv6NetToMediaTable");
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
DWORD
|
|
CountRoute(
|
|
IN IPV6_INFO_ROUTE_TABLE *RTE,
|
|
IN PVOID Arg1,
|
|
IN PVOID Arg2)
|
|
{
|
|
DWORD *pdwRouteCount = (DWORD *)Arg1;
|
|
DWORD *pdwAddrPrefixCount = (DWORD *)Arg2;
|
|
|
|
//
|
|
// Suppress system routes (used for loopback).
|
|
//
|
|
if (RTE->Type == RTE_TYPE_SYSTEM) {
|
|
return NO_ERROR;
|
|
}
|
|
|
|
(*pdwRouteCount)++;
|
|
|
|
if ((RTE->This.PrefixLength > 0)
|
|
&& (RTE->This.PrefixLength < 128)) {
|
|
(*pdwAddrPrefixCount)++;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadRoute(
|
|
IN IPV6_INFO_ROUTE_TABLE *RTE,
|
|
IN PVOID Arg1,
|
|
IN PVOID Arg2)
|
|
{
|
|
DWORD *pdwRouteCount = (DWORD *)Arg1;
|
|
DWORD *pdwAddrPrefixCount = (DWORD *)Arg2;
|
|
DWORD i;
|
|
PMIB_IPV6_ROUTE pRoute;
|
|
PMIB_IPV6_ADDR_PREFIX pPrefix;
|
|
|
|
//
|
|
// Suppress system routes (used for loopback).
|
|
//
|
|
if (RTE->Type == RTE_TYPE_SYSTEM) {
|
|
return NO_ERROR;
|
|
}
|
|
|
|
if (g_Cache.pRpcIpv6RouteTable.dwNumEntries < *pdwRouteCount) {
|
|
|
|
i = g_Cache.pRpcIpv6RouteTable.dwNumEntries++;
|
|
pRoute = &g_Cache.pRpcIpv6RouteTable.table[i];
|
|
pRoute->ipPrefix = RTE->This.Prefix;
|
|
pRoute->dwPrefixLength = RTE->This.PrefixLength;
|
|
pRoute->ipNextHop = RTE->This.Neighbor.Address;
|
|
pRoute->dwIndex = g_Cache.pRpcIpv6RouteTable.dwNumEntries;
|
|
pRoute->dwIfIndex = RTE->This.Neighbor.IF.Index;
|
|
if (!memcmp(&RTE->This.Neighbor.Address, &in6addr_any, sizeof(IN6_ADDR))) {
|
|
pRoute->dwType = 3; /* Local */
|
|
} else {
|
|
pRoute->dwType = 4; /* Remote */
|
|
}
|
|
pRoute->dwProtocol = RTE->Type;
|
|
pRoute->dwPolicy = 0;
|
|
pRoute->dwAge = 0;
|
|
pRoute->dwNextHopRDI = 0;
|
|
pRoute->dwMetric = RTE->Preference;
|
|
pRoute->dwWeight = 0;
|
|
pRoute->dwValid = 1;
|
|
}
|
|
|
|
if ((g_Cache.pRpcIpv6AddrPrefixTable.dwNumEntries < *pdwAddrPrefixCount)
|
|
&& (RTE->This.PrefixLength > 0)
|
|
&& (RTE->This.PrefixLength < 128)) {
|
|
|
|
i = g_Cache.pRpcIpv6AddrPrefixTable.dwNumEntries++;
|
|
pPrefix = &g_Cache.pRpcIpv6AddrPrefixTable.table[i];
|
|
pPrefix->dwIfIndex = RTE->This.Neighbor.IF.Index;
|
|
pPrefix->ipPrefix = RTE->This.Prefix;
|
|
pPrefix->dwPrefixLength = RTE->This.PrefixLength;
|
|
|
|
if (!memcmp(&RTE->This.Neighbor.Address, &in6addr_any, sizeof(IN6_ADDR))) {
|
|
pPrefix->dwOnLinkFlag = 1; /* True */
|
|
} else {
|
|
pPrefix->dwOnLinkFlag = 2; /* False */
|
|
}
|
|
|
|
//
|
|
// TODO: The stack doesn't currently store this information,
|
|
// so always report True for now.
|
|
//
|
|
pPrefix->dwAutonomousFlag = 1; /* True */
|
|
|
|
pPrefix->dwPreferredLifetime = RTE->PreferredLifetime;
|
|
pPrefix->dwValidLifetime = RTE->ValidLifetime;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
LoadIpv6RouteTable()
|
|
{
|
|
DWORD dwResult, dwOutBufLen = 0;
|
|
DWORD dwRouteCount = 0, dwAddrPrefixCount = 0, i;
|
|
|
|
TraceEnter("LoadIpv6RouteTable");
|
|
|
|
FreeIpv6RouteTable();
|
|
|
|
OpenIpv6();
|
|
|
|
//
|
|
// Count entries
|
|
//
|
|
ForEachRoute(CountRoute, &dwRouteCount, &dwAddrPrefixCount);
|
|
|
|
//
|
|
// Create the tables
|
|
//
|
|
if (dwRouteCount) {
|
|
g_Cache.pRpcIpv6RouteTable.table = HeapAlloc(g_hPrivateHeap, 0, dwRouteCount * sizeof(MIB_IPV6_ROUTE));
|
|
if (!g_Cache.pRpcIpv6RouteTable.table) {
|
|
TraceLeave("LoadIpv6RouteTable");
|
|
return GetLastError();
|
|
}
|
|
}
|
|
if (dwAddrPrefixCount) {
|
|
g_Cache.pRpcIpv6AddrPrefixTable.table = HeapAlloc(g_hPrivateHeap, 0, dwAddrPrefixCount * sizeof(MIB_IPV6_ADDR_PREFIX));
|
|
if (!g_Cache.pRpcIpv6AddrPrefixTable.table) {
|
|
FreeIpv6RouteTable();
|
|
TraceLeave("LoadIpv6RouteTable");
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
//
|
|
// Load entries
|
|
//
|
|
dwResult = ForEachRoute(LoadRoute, &dwRouteCount, &dwAddrPrefixCount);
|
|
|
|
qsort(g_Cache.pRpcIpv6RouteTable.table,
|
|
g_Cache.pRpcIpv6RouteTable.dwNumEntries,
|
|
sizeof(MIB_IPV6_ROUTE),
|
|
CompareIpv6RouteRow);
|
|
qsort(g_Cache.pRpcIpv6AddrPrefixTable.table,
|
|
g_Cache.pRpcIpv6AddrPrefixTable.dwNumEntries,
|
|
sizeof(MIB_IPV6_ADDR_PREFIX),
|
|
CompareIpv6AddrPrefixRow);
|
|
|
|
CloseHandle(g_hIpv6Handle);
|
|
|
|
TraceLeave("LoadIpv6RouteTable");
|
|
|
|
return dwResult;
|
|
}
|