658 lines
18 KiB
C
658 lines
18 KiB
C
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
net\routing\netsh\ip\protocols\msdpmib.c
|
|
|
|
Abstract:
|
|
|
|
Functions to get and display MSDP MIB information.
|
|
|
|
Author:
|
|
|
|
Dave Thaler 11/03/99
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
|
|
|
|
ULONG
|
|
QueryTagArray(
|
|
PTCHAR ArgumentArray[],
|
|
ULONG ArgumentCount,
|
|
TAG_TYPE TagTypeArray[],
|
|
ULONG TagTypeCount,
|
|
OUT PULONG* TagArray
|
|
);
|
|
|
|
//
|
|
// Flag for printing header
|
|
//
|
|
BOOL g_bMsdpFirst = TRUE;
|
|
HANDLE g_hConsole, g_hStdOut;
|
|
|
|
// This can have the other fields pfn etc
|
|
MIB_OBJECT_PARSER MsdpMIBObjectMap[] =
|
|
{
|
|
{TOKEN_MSDP_MIB_OBJECT_GLOBALSTATS,0,0,NULL},
|
|
{TOKEN_MSDP_MIB_OBJECT_PEERSTATS, 1,1,GetMsdpMIBIpAddress},
|
|
{TOKEN_MSDP_MIB_OBJECT_SA, 0,2,GetMsdpMIBSAIndex},
|
|
};
|
|
#define MAX_MSDP_MIB_OBJECTS (sizeof(MsdpMIBObjectMap)/sizeof(MIB_OBJECT_PARSER))
|
|
|
|
MSDP_MAGIC_TABLE MsdpMIBVar[] = {
|
|
{MIBID_MSDP_GLOBAL, PrintMsdpGlobalStats, 0},
|
|
{MIBID_MSDP_IPV4_PEER_ENTRY, PrintMsdpPeerStats, 4},
|
|
{MIBID_MSDP_SA_CACHE_ENTRY, PrintMsdpSA, 8},
|
|
};
|
|
|
|
DWORD
|
|
GetMsdpMIBIpAddress(
|
|
IN LPCWSTR *ppwcArguments,
|
|
IN ULONG ulArgumentIndex,
|
|
IN ULONG ulArgumentCount,
|
|
OUT PDWORD pdwIndices,
|
|
OUT PDWORD pdwNumParsed
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets the index IP address for peer Mib variable.
|
|
|
|
Arguments:
|
|
|
|
ppwcArguments - Argument array
|
|
ulArgumentIndex - Index of the first argument in array
|
|
pdwIndices - Indices specified in command
|
|
pdwNumParsed - Number of indices in command
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr;
|
|
ULONG i;
|
|
PULONG pulTagArray;
|
|
ULONG ulArgumentsLeft = ulArgumentCount - ulArgumentIndex;
|
|
TAG_TYPE TagTypeArray[] = { { TOKEN_OPT_REMADDR, FALSE, FALSE }
|
|
};
|
|
|
|
*pdwNumParsed = 0;
|
|
|
|
if (ulArgumentsLeft < 1)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
dwErr = QueryTagArray( &ppwcArguments[ulArgumentIndex],
|
|
ulArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&pulTagArray );
|
|
|
|
if (dwErr is NO_ERROR) {
|
|
for (i=0; i<ulArgumentsLeft; i++) {
|
|
switch(pulTagArray ? pulTagArray[i] : i) {
|
|
case 0: { // remaddr
|
|
pdwIndices[0] = GetIpAddress(ppwcArguments[i+
|
|
ulArgumentIndex]);
|
|
(*pdwNumParsed)++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
dwErr = ERROR_SHOW_USAGE;
|
|
}
|
|
|
|
if (pulTagArray) { FREE(pulTagArray); }
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
GetMsdpMIBSAIndex(
|
|
IN LPCWSTR *ppwcArguments,
|
|
IN ULONG ulArgumentIndex,
|
|
IN ULONG ulArgumentCount,
|
|
OUT PDWORD pdwIndices,
|
|
OUT PDWORD pdwNumParsed
|
|
)
|
|
{
|
|
DWORD dwErr;
|
|
ULONG i;
|
|
ULONG ulArgumentsLeft = ulArgumentCount - ulArgumentIndex;
|
|
PULONG pulTagArray;
|
|
TAG_TYPE TagTypeArray[] = { { TOKEN_OPT_GROUPADDR, FALSE, FALSE },
|
|
{ TOKEN_OPT_SOURCEADDR, FALSE, FALSE },
|
|
};
|
|
|
|
*pdwNumParsed = 0;
|
|
|
|
if (ulArgumentsLeft < 1)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
dwErr = QueryTagArray( &ppwcArguments[ulArgumentIndex],
|
|
ulArgumentsLeft,
|
|
TagTypeArray,
|
|
NUM_TAGS_IN_TABLE(TagTypeArray),
|
|
&pulTagArray );
|
|
|
|
if (dwErr is NO_ERROR) {
|
|
for (i=0; i<ulArgumentsLeft; i++) {
|
|
switch(pulTagArray ? pulTagArray[i] : i) {
|
|
case 0: { // grpaddr
|
|
pdwIndices[0] = GetIpAddress(ppwcArguments[i+
|
|
ulArgumentIndex]);
|
|
(*pdwNumParsed)++;
|
|
break;
|
|
}
|
|
case 1: { // srcaddr
|
|
pdwIndices[1] = GetIpAddress(ppwcArguments[i+
|
|
ulArgumentIndex]);
|
|
(*pdwNumParsed)++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pulTagArray) { FREE(pulTagArray); }
|
|
return dwErr;
|
|
}
|
|
|
|
PWCHAR
|
|
GetTceStateString(
|
|
DWORD dwState
|
|
)
|
|
{
|
|
PWCHAR pwszStr;
|
|
static WCHAR buff[80];
|
|
VALUE_STRING ppsList[] = {{MSDP_STATE_IDLE, STRING_IDLE},
|
|
{MSDP_STATE_CONNECT, STRING_CONNECT},
|
|
{MSDP_STATE_ACTIVE, STRING_ACTIVE},
|
|
{MSDP_STATE_OPENSENT, STRING_OPENSENT},
|
|
{MSDP_STATE_OPENCONFIRM, STRING_OPENCONFIRM},
|
|
{MSDP_STATE_ESTABLISHED, STRING_ESTABLISHED},
|
|
};
|
|
DWORD dwNum = sizeof(ppsList)/sizeof(VALUE_STRING), i;
|
|
DWORD dwMsgId = 0;
|
|
|
|
for (i=0; i<dwNum; i++)
|
|
{
|
|
if (dwState is ppsList[i].dwValue)
|
|
{
|
|
dwMsgId = ppsList[i].dwStringId;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dwMsgId)
|
|
{
|
|
pwszStr = MakeString( g_hModule, dwMsgId);
|
|
wcscpy(buff, pwszStr);
|
|
FreeString(pwszStr);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(buff, L"%d", dwState);
|
|
}
|
|
|
|
return buff;
|
|
}
|
|
|
|
DWORD
|
|
HandleMsdpMibShowObject(
|
|
PWCHAR pwszMachine,
|
|
PWCHAR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parses command to get MIB object and optional parameters
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
DWORD dwIndices[MAX_NUM_INDICES];
|
|
DWORD dwNumParsed = 0;
|
|
MIB_OPAQUE_QUERY rgQueryBuff[2];
|
|
PMIB_OPAQUE_QUERY pQuery = rgQueryBuff;
|
|
PMIB_OPAQUE_INFO pRpcInfo;
|
|
DWORD dwQuerySize;
|
|
BOOL bFound = FALSE,bOptPresent = FALSE;
|
|
DWORD dwRefreshRate;
|
|
DWORD dwOutEntrySize;
|
|
DWORD i,dwResult,dwErr;
|
|
DWORD dwMIBIndex, dwIndex;
|
|
BOOL bIndex = FALSE, dwType;
|
|
DWORD dwRR = 0, dwInd = 0;
|
|
HANDLE hMib;
|
|
DWORD dwDisplayInfoId, dwDisplayInfoType, dwOptVar;
|
|
DWORD dwOutSize;
|
|
|
|
VERIFY_INSTALLED(MS_IP_MSDP, L"MSDP");
|
|
|
|
//
|
|
// Match MIB object
|
|
//
|
|
|
|
g_hMibServer = hMibServer;
|
|
|
|
ppwcArguments += (dwCurrentIndex-1);
|
|
dwArgCount -= (dwCurrentIndex-1);
|
|
dwCurrentIndex = 1;
|
|
|
|
DEBUG1("In MSDP MIB Show : %s\n",ppwcArguments[0]);
|
|
|
|
for (i = 0; i < MAX_MSDP_MIB_OBJECTS; i++)
|
|
{
|
|
if (MatchToken(ppwcArguments[0],MsdpMIBObjectMap[i].pwszMIBObj))
|
|
{
|
|
dwIndex = i;
|
|
bFound = TRUE;
|
|
|
|
DEBUG("found");
|
|
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (!bFound)
|
|
{
|
|
return ERROR_CMD_NOT_FOUND;
|
|
}
|
|
|
|
#if 0
|
|
if ((dwArgCount > 1) && IsHelpToken(ppwcArguments[1]))
|
|
{
|
|
DisplayMessage(g_hModule,
|
|
MsdpMIBObjectMap[i].dwCmdHelpToken,
|
|
MsdpMIBObjectMap[i].pwszMIBObj);
|
|
return NO_ERROR;
|
|
}
|
|
#endif
|
|
|
|
if (MsdpMIBObjectMap[dwIndex].pfnMIBObjParser)
|
|
{
|
|
dwErr = (*MsdpMIBObjectMap[dwIndex].pfnMIBObjParser)(ppwcArguments,
|
|
1 + dwInd,
|
|
dwArgCount,
|
|
dwIndices,
|
|
&dwNumParsed);
|
|
|
|
if (dwErr isnot NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Convert refresh rate to msec
|
|
//
|
|
|
|
dwRR *= 1000;
|
|
|
|
dwMIBIndex = dwIndex;
|
|
|
|
pQuery->dwVarId = MsdpMIBVar[dwMIBIndex].dwId;
|
|
|
|
if (!InitializeConsole(&dwRR, &hMib, &g_hConsole))
|
|
{
|
|
return ERROR_INIT_DISPLAY;
|
|
}
|
|
|
|
for ( ; ; )
|
|
{
|
|
if(dwRR)
|
|
{
|
|
DisplayMessageToConsole(g_hModule, g_hConsole, MSG_CTRL_C_TO_QUIT);
|
|
}
|
|
|
|
// See if we just need to do a GET
|
|
if (dwNumParsed is MsdpMIBObjectMap[dwIndex].dwNumArgs)
|
|
{
|
|
pQuery->rgdwVarIndex[0] = 0;
|
|
for (i=0; i<MsdpMIBObjectMap[dwIndex].dwNumArgs; i++)
|
|
{
|
|
pQuery->rgdwVarIndex[i] = dwIndices[i];
|
|
}
|
|
|
|
dwResult = MprAdminMIBEntryGet(hMibServer,
|
|
PID_IP,
|
|
MS_IP_MSDP,
|
|
(LPVOID) pQuery,
|
|
sizeof(MIB_OPAQUE_QUERY)
|
|
+ MsdpMIBVar[dwMIBIndex].ulIndexBytes-sizeof(DWORD),
|
|
(LPVOID *) &pRpcInfo,
|
|
&dwOutSize );
|
|
|
|
if (( dwResult isnot NO_ERROR ) and (dwResult isnot ERROR_NOT_FOUND))
|
|
{
|
|
DisplayMessageToConsole( g_hModule, g_hConsole, MSG_IP_DIM_ERROR, dwResult );
|
|
break;
|
|
}
|
|
|
|
if ( pRpcInfo is NULL )
|
|
{
|
|
break;
|
|
}
|
|
|
|
(*MsdpMIBVar[dwMIBIndex].pfnPrintFunction)(pRpcInfo, FORMAT_VERBOSE);
|
|
|
|
MprAdminMIBBufferFree( (PVOID) pRpcInfo );
|
|
}
|
|
else if (dwNumParsed is 0)
|
|
{
|
|
// Display All
|
|
g_bMsdpFirst = TRUE;
|
|
|
|
dwResult = MprAdminMIBEntryGetFirst(hMibServer,
|
|
PID_IP,
|
|
MS_IP_MSDP,
|
|
(LPVOID) pQuery,
|
|
sizeof(MIB_OPAQUE_INFO)
|
|
+ MsdpMIBVar[dwMIBIndex].ulIndexBytes-sizeof(DWORD),
|
|
(LPVOID *) &pRpcInfo,
|
|
&dwOutSize );
|
|
|
|
if (( dwResult isnot NO_ERROR ) and (dwResult isnot ERROR_NO_MORE_ITEMS))
|
|
{
|
|
DisplayMessageToConsole( g_hModule, g_hConsole, MSG_IP_DIM_ERROR, dwResult );
|
|
break;
|
|
}
|
|
|
|
if ( pRpcInfo is NULL )
|
|
{
|
|
DisplayMessageToConsole( g_hModule, g_hConsole, MSG_IP_NO_ENTRIES );
|
|
break;
|
|
}
|
|
|
|
(*MsdpMIBVar[dwMIBIndex].pfnPrintFunction)(pRpcInfo, FORMAT_TABLE);
|
|
|
|
g_bMsdpFirst = FALSE;
|
|
|
|
do
|
|
{
|
|
// pQuery->rgdwVarIndex[0] = pRpcInfo->IMGOD_IfIndex;
|
|
|
|
//
|
|
// prepare for next request
|
|
//
|
|
|
|
CopyMemory(pQuery->rgdwVarIndex, pRpcInfo->rgbyData,
|
|
MsdpMIBVar[dwMIBIndex].ulIndexBytes );
|
|
|
|
MprAdminMIBBufferFree( (PVOID) pRpcInfo );
|
|
pRpcInfo = NULL;
|
|
|
|
DEBUG2("calling next with index %d", pQuery->rgdwVarIndex[0]);
|
|
|
|
dwResult = MprAdminMIBEntryGetNext(hMibServer,
|
|
PID_IP,
|
|
MS_IP_MSDP,
|
|
(LPVOID) pQuery,
|
|
sizeof(MIB_OPAQUE_QUERY)
|
|
+ MsdpMIBVar[dwMIBIndex].ulIndexBytes-sizeof(DWORD),
|
|
(LPVOID *) &pRpcInfo,
|
|
&dwOutSize );
|
|
|
|
if (dwResult is ERROR_NO_MORE_ITEMS)
|
|
{
|
|
g_bMsdpFirst = TRUE;
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
if ( dwResult isnot NO_ERROR )
|
|
{
|
|
g_bMsdpFirst = TRUE;
|
|
break;
|
|
}
|
|
|
|
if ( pRpcInfo is NULL )
|
|
{
|
|
g_bMsdpFirst = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (pQuery->dwVarId isnot pRpcInfo->dwId)
|
|
{
|
|
g_bMsdpFirst = TRUE;
|
|
break;
|
|
}
|
|
|
|
(*MsdpMIBVar[dwMIBIndex].pfnPrintFunction)(pRpcInfo, FORMAT_TABLE);
|
|
|
|
} while (1);
|
|
}
|
|
else
|
|
{
|
|
// partially-specified index
|
|
|
|
g_bMsdpFirst = TRUE;
|
|
|
|
pQuery->rgdwVarIndex[0] = 0;
|
|
for (i=0; i<dwNumParsed; i++)
|
|
{
|
|
pQuery->rgdwVarIndex[i] = dwIndices[i];
|
|
}
|
|
for (; i<MsdpMIBObjectMap[dwIndex].dwNumArgs; i++)
|
|
{
|
|
pQuery->rgdwVarIndex[i] = 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
dwResult = MprAdminMIBEntryGetNext(hMibServer,
|
|
PID_IP,
|
|
MS_IP_MSDP,
|
|
(LPVOID) pQuery,
|
|
sizeof(MIB_OPAQUE_QUERY)
|
|
+ MsdpMIBVar[dwMIBIndex].ulIndexBytes-sizeof(DWORD),
|
|
(LPVOID *) &pRpcInfo,
|
|
&dwOutSize );
|
|
|
|
if (dwResult is NO_ERROR)
|
|
{
|
|
// See if we've gone too far
|
|
for (i=0; i<dwNumParsed; i++)
|
|
{
|
|
// All index fields are DWORDs
|
|
if (memcmp(pQuery->rgdwVarIndex, pRpcInfo->rgbyData,
|
|
dwNumParsed * sizeof(DWORD)))
|
|
{
|
|
dwResult = ERROR_NO_MORE_ITEMS;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwResult is ERROR_NO_MORE_ITEMS)
|
|
{
|
|
g_bMsdpFirst = TRUE;
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
if ( dwResult isnot NO_ERROR )
|
|
{
|
|
g_bMsdpFirst = TRUE;
|
|
break;
|
|
}
|
|
|
|
if ( pRpcInfo is NULL )
|
|
{
|
|
g_bMsdpFirst = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (pQuery->dwVarId isnot pRpcInfo->dwId)
|
|
{
|
|
g_bMsdpFirst = TRUE;
|
|
break;
|
|
}
|
|
|
|
(*MsdpMIBVar[dwMIBIndex].pfnPrintFunction)(pRpcInfo, FORMAT_TABLE);
|
|
|
|
//
|
|
// prepare for next request
|
|
//
|
|
|
|
CopyMemory(pQuery->rgdwVarIndex, pRpcInfo->rgbyData,
|
|
MsdpMIBVar[dwMIBIndex].ulIndexBytes );
|
|
|
|
MprAdminMIBBufferFree( (PVOID) pRpcInfo );
|
|
pRpcInfo = NULL;
|
|
g_bMsdpFirst = FALSE;
|
|
|
|
} while (1);
|
|
}
|
|
|
|
if (!RefreshConsole(hMib, g_hConsole, dwRR))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
VOID
|
|
PrintMsdpGlobalStats(
|
|
PMIB_OPAQUE_INFO pRpcInfo,
|
|
DWORD dwFormat
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints msdp global statistics
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
WCHAR wszRouterId[20];
|
|
|
|
PMSDP_GLOBAL_ENTRY pEntry = (PMSDP_GLOBAL_ENTRY)(pRpcInfo->rgbyData);
|
|
|
|
IP_TO_TSTR(wszRouterId, &pEntry->dwRouterId);
|
|
|
|
DisplayMessageToConsole(g_hModule,g_hConsole,MSG_MSDP_GLOBAL_STATS,
|
|
pEntry->ulNumSACacheEntries,
|
|
wszRouterId);
|
|
}
|
|
|
|
VOID
|
|
PrintMsdpSA(
|
|
PMIB_OPAQUE_INFO pRpcInfo,
|
|
DWORD dwFormat
|
|
)
|
|
{
|
|
PMSDP_SA_CACHE_ENTRY psa;
|
|
WCHAR wszGroupAddress[20];
|
|
WCHAR wszSourceAddress[20];
|
|
WCHAR wszOriginAddress[20];
|
|
WCHAR wszLearnedFromAddress[20];
|
|
WCHAR wszRPFPeerAddress[20];
|
|
DWORD dwId = (dwFormat is FORMAT_TABLE)? MSG_MSDP_SA_INFO :
|
|
MSG_MSDP_SA_INFO_EX;
|
|
|
|
if (g_bMsdpFirst && (dwFormat is FORMAT_TABLE))
|
|
{
|
|
DisplayMessageToConsole(g_hModule,g_hConsole,MSG_MSDP_SA_INFO_HEADER);
|
|
}
|
|
|
|
psa = (PMSDP_SA_CACHE_ENTRY)(pRpcInfo->rgbyData);
|
|
|
|
IP_TO_TSTR(wszGroupAddress, &psa->ipGroupAddr);
|
|
IP_TO_TSTR(wszSourceAddress, &psa->ipSourceAddr);
|
|
IP_TO_TSTR(wszOriginAddress, &psa->ipOriginRP);
|
|
IP_TO_TSTR(wszLearnedFromAddress, &psa->ipPeerLearnedFrom);
|
|
IP_TO_TSTR(wszRPFPeerAddress, &psa->ipRPFPeer);
|
|
|
|
DisplayMessageToConsole(g_hModule, g_hConsole,
|
|
dwId,
|
|
wszGroupAddress,
|
|
wszSourceAddress,
|
|
wszOriginAddress,
|
|
wszLearnedFromAddress,
|
|
wszRPFPeerAddress,
|
|
psa->ulInSAs,
|
|
psa->ulUpTime/100,
|
|
psa->ulExpiryTime/100);
|
|
}
|
|
|
|
VOID
|
|
PrintMsdpPeerStats(
|
|
PMIB_OPAQUE_INFO pRpcInfo,
|
|
DWORD dwFormat
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints msdp neighbor stats
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
PMSDP_IPV4_PEER_ENTRY pPeer;
|
|
WCHAR wszAddr[ADDR_LENGTH + 1];
|
|
|
|
if (g_bMsdpFirst && (dwFormat is FORMAT_TABLE))
|
|
{
|
|
DisplayMessageToConsole(g_hModule,g_hConsole,MSG_MSDP_PEER_STATS_HEADER);
|
|
}
|
|
|
|
pPeer = (PMSDP_IPV4_PEER_ENTRY)(pRpcInfo->rgbyData);
|
|
|
|
MakeUnicodeIpAddr(wszAddr, inet_ntoa(*((struct in_addr *)
|
|
(&pPeer->ipRemoteAddress))));
|
|
|
|
DisplayMessageToConsole(g_hModule, g_hConsole,
|
|
(dwFormat is FORMAT_TABLE)? MSG_MSDP_PEER_STATS
|
|
: MSG_MSDP_PEER_STATS_EX,
|
|
wszAddr,
|
|
GetTceStateString(pPeer->dwState),
|
|
pPeer->ulRPFFailures,
|
|
pPeer->ulInSAs,
|
|
pPeer->ulOutSAs,
|
|
pPeer->ulInSARequests,
|
|
pPeer->ulOutSARequests,
|
|
pPeer->ulInSAResponses,
|
|
pPeer->ulOutSAResponses,
|
|
pPeer->ulInControlMessages,
|
|
pPeer->ulOutControlMessages,
|
|
pPeer->ulFsmEstablishedTransitions,
|
|
pPeer->ulFsmEstablishedTime,
|
|
pPeer->ulInMessageElapsedTime);
|
|
}
|