1131 lines
27 KiB
C
1131 lines
27 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1996 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
mibfuncs.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Sample subagent instrumentation callbacks.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
// defined in iphlpapi.dll. This is a private api, which is
|
||
|
// not declared in any header file.
|
||
|
|
||
|
DWORD
|
||
|
GetIgmpList(IN IPAddr NTEAddr,
|
||
|
OUT IPAddr *pIgmpList,
|
||
|
OUT PULONG dwOutBufLen
|
||
|
);
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// local typedefs
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
typedef enum {
|
||
|
CONFIG_TYPE, STATS_TYPE
|
||
|
} INFO_TYPE;
|
||
|
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// Local Prototypes
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
DWORD
|
||
|
ConnectToRouter(
|
||
|
);
|
||
|
|
||
|
DWORD
|
||
|
GetInterfaceInfo(
|
||
|
DWORD ActionId,
|
||
|
DWORD *IfIndex,
|
||
|
PIGMP_MIB_GET_OUTPUT_DATA *ppResponse,
|
||
|
INFO_TYPE InfoType
|
||
|
);
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetCacheEntry(
|
||
|
DWORD ActionId,
|
||
|
DWORD IfIndex,
|
||
|
DWORD Group,
|
||
|
DWORD *pNextGroup,
|
||
|
PIGMP_MIB_GET_OUTPUT_DATA *ppResponse
|
||
|
);
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
// GetInterfaceInfo
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
DWORD
|
||
|
GetInterfaceInfo(
|
||
|
DWORD ActionId,
|
||
|
DWORD *pIfIndex,
|
||
|
PIGMP_MIB_GET_OUTPUT_DATA *ppResponse,
|
||
|
INFO_TYPE infoType
|
||
|
)
|
||
|
/*++
|
||
|
Routine Description:
|
||
|
Makes a call to igmp to get the interface config and stats and
|
||
|
returns that info to mib.
|
||
|
Return values:
|
||
|
MIB_S_ENTRY_NOT_FOUND MIB_S_NO_MORE_ENTRIES MIB_S_INVALID_PARAMETER
|
||
|
--*/
|
||
|
{
|
||
|
IGMP_MIB_GET_INPUT_DATA Query;
|
||
|
DWORD dwErr = NO_ERROR, dwOutSize;
|
||
|
|
||
|
*ppResponse = NULL;
|
||
|
|
||
|
ZeroMemory(&Query, sizeof(Query));
|
||
|
Query.TypeId = (infoType==CONFIG_TYPE) ? IGMP_IF_CONFIG_ID: IGMP_IF_STATS_ID;
|
||
|
Query.Flags = 0;
|
||
|
Query.Count = 1;
|
||
|
Query.IfIndex = *pIfIndex;
|
||
|
|
||
|
if ( (*pIfIndex==0) && (ActionId==MIB_ACTION_GETNEXT) )
|
||
|
ActionId = MIB_ACTION_GETFIRST;
|
||
|
|
||
|
switch (ActionId) {
|
||
|
|
||
|
//
|
||
|
// ERROR_INVALID_PARAMETER is returned when there is no
|
||
|
// interface with the given index
|
||
|
// RPC_S_SERVER_UNAVAILABLE is returned when the router
|
||
|
// isn't running.
|
||
|
//
|
||
|
|
||
|
case MIB_ACTION_GET :
|
||
|
{
|
||
|
IGMP_MIB_GET(&Query, sizeof(Query), ppResponse,
|
||
|
&dwOutSize, dwErr);
|
||
|
|
||
|
if (dwErr==ERROR_INVALID_PARAMETER
|
||
|
|| dwErr==RPC_S_SERVER_UNAVAILABLE
|
||
|
|| dwErr==MIB_S_NO_MORE_ENTRIES)
|
||
|
{
|
||
|
dwErr = MIB_S_ENTRY_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case MIB_ACTION_GETFIRST :
|
||
|
{
|
||
|
IGMP_MIB_GETFIRST(&Query, sizeof(Query), ppResponse,
|
||
|
&dwOutSize, dwErr);
|
||
|
|
||
|
if (dwErr==ERROR_INVALID_PARAMETER
|
||
|
|| dwErr==RPC_S_SERVER_UNAVAILABLE
|
||
|
|| dwErr==MIB_S_NO_MORE_ENTRIES)
|
||
|
{
|
||
|
dwErr = MIB_S_NO_MORE_ENTRIES;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
case MIB_ACTION_GETNEXT :
|
||
|
{
|
||
|
IGMP_MIB_GETNEXT(&Query, sizeof(Query), ppResponse,
|
||
|
&dwOutSize, dwErr);
|
||
|
|
||
|
if (dwErr==ERROR_INVALID_PARAMETER
|
||
|
|| dwErr==RPC_S_SERVER_UNAVAILABLE
|
||
|
|| dwErr==MIB_S_NO_MORE_ENTRIES)
|
||
|
{
|
||
|
dwErr = MIB_S_NO_MORE_ENTRIES;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default :
|
||
|
{
|
||
|
dwErr = MIB_S_INVALID_PARAMETER;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwErr!=NO_ERROR)
|
||
|
*ppResponse = NULL;
|
||
|
|
||
|
else
|
||
|
*pIfIndex = Query.IfIndex;
|
||
|
|
||
|
return dwErr;
|
||
|
|
||
|
} //end GetInterfaceInfo
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// igmpInterfaceEntry table (1,3,6,1,3,59,1,1,1,1) //
|
||
|
// //
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
UINT
|
||
|
get_igmpInterfaceEntry(
|
||
|
UINT ActionId,
|
||
|
AsnAny *ObjectArray,
|
||
|
UINT *ErrorIndex
|
||
|
)
|
||
|
/*++
|
||
|
Routine Description:
|
||
|
Get the InterfaceEntry for snmp. Have to get the InterfaceConfig and
|
||
|
InterfaceStats for the interface from igmp router.
|
||
|
--*/
|
||
|
{
|
||
|
DWORD dwErr=NO_ERROR;
|
||
|
PIGMP_MIB_GET_OUTPUT_DATA pResponseConfig, pResponseStats;
|
||
|
PIGMP_MIB_IF_CONFIG pConfig;
|
||
|
PIGMP_MIB_IF_STATS pStats;
|
||
|
DWORD IfIndex, dwValue;
|
||
|
buf_igmpInterfaceEntry *pMibIfEntry
|
||
|
= (buf_igmpInterfaceEntry*)ObjectArray;
|
||
|
DWORD dwTmpActionId;
|
||
|
|
||
|
|
||
|
|
||
|
TraceEnter("get_igmpInterfaceEntry");
|
||
|
|
||
|
|
||
|
// get the interface index
|
||
|
|
||
|
IfIndex = GET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceIfIndex, 0);
|
||
|
|
||
|
TRACE1("get_igmpInterfaceEntry called with IfIndex:%d", IfIndex);
|
||
|
|
||
|
//
|
||
|
// get interface config
|
||
|
//
|
||
|
|
||
|
dwTmpActionId = ActionId;
|
||
|
|
||
|
while (1) {
|
||
|
|
||
|
dwErr = GetInterfaceInfo(
|
||
|
dwTmpActionId,
|
||
|
&IfIndex,
|
||
|
&pResponseConfig,
|
||
|
CONFIG_TYPE
|
||
|
);
|
||
|
|
||
|
|
||
|
// return if error
|
||
|
|
||
|
if (dwErr!=NO_ERROR) {
|
||
|
TraceError(dwErr);
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
pConfig = (PIGMP_MIB_IF_CONFIG) pResponseConfig->Buffer;
|
||
|
|
||
|
|
||
|
//
|
||
|
// should ignore proxy interface (unless the mode is MIB_ACTION_GET)
|
||
|
//
|
||
|
|
||
|
if ( (pConfig->IgmpProtocolType==IGMP_PROXY)
|
||
|
&& ( (ActionId==MIB_ACTION_GETFIRST)||(ActionId==MIB_ACTION_GETNEXT)) )
|
||
|
{
|
||
|
dwTmpActionId = MIB_ACTION_GETNEXT;
|
||
|
MprAdminMIBBufferFree(pResponseConfig);
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get interface stats
|
||
|
// use MIB_GET as IfIndex has been updated by the previous call
|
||
|
//
|
||
|
|
||
|
dwErr = GetInterfaceInfo(
|
||
|
MIB_ACTION_GET,
|
||
|
&IfIndex,
|
||
|
&pResponseStats,
|
||
|
STATS_TYPE
|
||
|
);
|
||
|
|
||
|
|
||
|
// return if error
|
||
|
|
||
|
if (dwErr!=NO_ERROR) {
|
||
|
MprAdminMIBBufferFree(pResponseConfig);
|
||
|
TraceError(dwErr);
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
TRACE1("get_igmpInterfaceEntry returned info for interface:%d",
|
||
|
IfIndex);
|
||
|
|
||
|
|
||
|
//
|
||
|
// fill in the required fields and return the MibIfEntry
|
||
|
//
|
||
|
|
||
|
pStats = (PIGMP_MIB_IF_STATS) pResponseStats->Buffer;
|
||
|
|
||
|
|
||
|
//
|
||
|
// set index for following getnext operation, (if any)
|
||
|
//
|
||
|
FORCE_SET_ASN_INTEGER(&(pMibIfEntry->igmpInterfaceIfIndex),
|
||
|
IfIndex);
|
||
|
|
||
|
|
||
|
// get igmpInterfaceQueryInterval in seconds
|
||
|
|
||
|
SET_ASN_INTEGER(&(pMibIfEntry->igmpInterfaceQueryInterval),
|
||
|
pConfig->GenQueryInterval);
|
||
|
|
||
|
|
||
|
//
|
||
|
// if Igmp is activated on that interface, then the state is set
|
||
|
// to active(1), else it is set to notInService(2)
|
||
|
//
|
||
|
|
||
|
if ((pStats->State&IGMP_STATE_ACTIVATED) == IGMP_STATE_ACTIVATED) {
|
||
|
SET_ASN_INTEGER(&(pMibIfEntry->igmpInterfaceStatus), 1);
|
||
|
}
|
||
|
else {
|
||
|
SET_ASN_INTEGER(&(pMibIfEntry->igmpInterfaceStatus), 2);
|
||
|
}
|
||
|
|
||
|
|
||
|
// set igmpInterfaceVersion
|
||
|
|
||
|
if (pConfig->IgmpProtocolType == IGMP_ROUTER_V1) {
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceVersion, 1);
|
||
|
}
|
||
|
else if (pConfig->IgmpProtocolType == IGMP_ROUTER_V2) {
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceVersion, 2);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// set igmpInterfaceQuerier
|
||
|
|
||
|
SET_ASN_IP_ADDRESS(&pMibIfEntry->igmpInterfaceQuerier,
|
||
|
&pMibIfEntry->igmpInterfaceQuerierBuf,
|
||
|
pStats->QuerierIpAddr);
|
||
|
|
||
|
|
||
|
// set igmpInterfaceQueryMaxResponseTime in seconds
|
||
|
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceQueryMaxResponseTime,
|
||
|
pConfig->GenQueryMaxResponseTime);
|
||
|
|
||
|
|
||
|
|
||
|
// todo: how can this value be set. This should be part of igmp host
|
||
|
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceVersion1QuerierTimer,
|
||
|
pStats->V1QuerierPresentTimeLeft);
|
||
|
|
||
|
SET_ASN_COUNTER(&pMibIfEntry->igmpInterfaceWrongVersionQueries,
|
||
|
pStats->WrongVersionQueries);
|
||
|
|
||
|
|
||
|
// number of times a group entry was added to the group table
|
||
|
|
||
|
SET_ASN_COUNTER(&pMibIfEntry->igmpInterfaceJoins,
|
||
|
pStats->GroupMembershipsAdded);
|
||
|
|
||
|
SET_ASN_GAUGE(&pMibIfEntry->igmpInterfaceGroups,
|
||
|
pStats->CurrentGroupMemberships);
|
||
|
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceRobustness,
|
||
|
pConfig->RobustnessVariable);
|
||
|
|
||
|
|
||
|
// set igmpInterfaceLastMembQueryInterval in 10ths of secs
|
||
|
// the value is initially in ms.
|
||
|
|
||
|
dwValue = pConfig->LastMemQueryInterval / 100;
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceLastMembQueryInterval,
|
||
|
dwValue);
|
||
|
|
||
|
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceProxyIfIndex,
|
||
|
pStats->ProxyIfIndex);
|
||
|
|
||
|
|
||
|
// seconds since igmpInterfaceQuerier was last changed
|
||
|
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceQuerierUpTime,
|
||
|
pStats->LastQuerierChangeTime);
|
||
|
|
||
|
SET_ASN_INTEGER(&pMibIfEntry->igmpInterfaceQuerierExpiryTime,
|
||
|
pStats->QuerierPresentTimeLeft);
|
||
|
|
||
|
MprAdminMIBBufferFree(pResponseConfig);
|
||
|
MprAdminMIBBufferFree(pResponseStats);
|
||
|
|
||
|
TraceLeave("get_igmpInterfaceEntry");
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ValidateInterfaceConfig(
|
||
|
IN AsnAny *objectArray
|
||
|
)
|
||
|
{
|
||
|
DWORD dwRes, IfIndex,
|
||
|
dwValue = 0, dwGenQueryInterval, dwMaxRespTime,
|
||
|
dwRobustness;
|
||
|
sav_igmpInterfaceEntry *pIfConfig = (sav_igmpInterfaceEntry*) objectArray;
|
||
|
|
||
|
|
||
|
dwRes = MIB_S_INVALID_PARAMETER;
|
||
|
|
||
|
BEGIN_BREAKOUT_BLOCK {
|
||
|
|
||
|
|
||
|
//
|
||
|
// get the interface index and make sure that it is not 0
|
||
|
//
|
||
|
IfIndex = GET_ASN_INTEGER(&pIfConfig->igmpInterfaceIfIndex, 0);
|
||
|
|
||
|
if (IfIndex==0) {
|
||
|
TRACE0("Call made for invalid interface index");
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// verify igmpInterfaceQueryInterval. Enforce min value of 10 sec
|
||
|
// to prevent trashing the network.
|
||
|
//
|
||
|
dwGenQueryInterval = GET_ASN_INTEGER(
|
||
|
&pIfConfig->igmpInterfaceQueryInterval, 0
|
||
|
);
|
||
|
|
||
|
if (dwGenQueryInterval<10) {
|
||
|
TRACE2("IgmpInterfaceQueryInterval:%d for interface:%d less than "
|
||
|
"minimum value of 10 secs",
|
||
|
dwValue, IfIndex);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Ignore interface status. Do not allow interface being enabled through snmp
|
||
|
//
|
||
|
|
||
|
|
||
|
//
|
||
|
// Igmp versions 1 and 2 currently supported
|
||
|
//
|
||
|
dwValue = GET_ASN_INTEGER(&pIfConfig->igmpInterfaceVersion, 0);
|
||
|
|
||
|
if ( (dwValue!=1) && (dwValue!=2) ) {
|
||
|
TRACE2("Invalid Igmp version:%d for interface:%d", dwValue, IfIndex);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// check InterfaceQueryMaxResponseTime
|
||
|
// NOTE: it is in units of 10ths of a second
|
||
|
//
|
||
|
dwMaxRespTime = GET_ASN_INTEGER(
|
||
|
&pIfConfig->igmpInterfaceQueryMaxResponseTime,
|
||
|
0);
|
||
|
|
||
|
// Enforce a min of 1 sec
|
||
|
|
||
|
if (dwValue<10) {
|
||
|
TRACE2("igmpInterfaceQueryMaxResponseTime:%d for interface:%d"
|
||
|
"should not be less than 10", dwValue, IfIndex);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// Absurd if value greater than GenQueryInterval*10 (conv to 10th of sec).
|
||
|
|
||
|
if (dwValue>dwGenQueryInterval*10) {
|
||
|
TRACE3("QueryMaxResponseTime:%d for interface:%d "
|
||
|
"should not be less than GenQueryInterval:%d",
|
||
|
dwValue, IfIndex, dwGenQueryInterval);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// igmpInterfaceRobustness must not be 0. If it is 1, print trace but
|
||
|
// do not break.
|
||
|
//
|
||
|
dwRobustness = GET_ASN_INTEGER(&pIfConfig->igmpInterfaceRobustness, 0);
|
||
|
|
||
|
if (dwValue==0) {
|
||
|
TRACE1("IgmpInterfaceRobustness for interface:%d cannot be set to 0",
|
||
|
IfIndex);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (dwValue!=1) {
|
||
|
TRACE1("Warning: InterfaceRobustness for interface:%d being set to 1",
|
||
|
IfIndex);
|
||
|
}
|
||
|
|
||
|
// no check for igmpInterfaceProxyIfIndex.
|
||
|
|
||
|
|
||
|
|
||
|
// limit max LastMemQueryInterval to GroupMembershipTimeout
|
||
|
|
||
|
dwValue = GET_ASN_INTEGER(&pIfConfig->igmpInterfaceLastMembQueryInterval,
|
||
|
0);
|
||
|
if (dwValue>dwRobustness*dwGenQueryInterval + dwMaxRespTime) {
|
||
|
TRACE3("LastMembQueryInterval:%d for interface:%d should not be "
|
||
|
"higher than GroupMembershipTimeout:%d",
|
||
|
dwValue, IfIndex,
|
||
|
dwRobustness*dwGenQueryInterval + dwMaxRespTime
|
||
|
);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// if reached here, then there is no error
|
||
|
|
||
|
dwRes = NO_ERROR;
|
||
|
|
||
|
} END_BREAKOUT_BLOCK;
|
||
|
|
||
|
return dwRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
SetInterfaceConfig(
|
||
|
IN AsnAny * objectArray
|
||
|
)
|
||
|
{
|
||
|
DWORD dwRes = (DWORD) -1,
|
||
|
dwGetSize = 0,
|
||
|
dwSetSize = 0,
|
||
|
IfIndex, dwValue;
|
||
|
|
||
|
sav_igmpInterfaceEntry *pNewIfConfig
|
||
|
= (sav_igmpInterfaceEntry*) objectArray;
|
||
|
|
||
|
PIGMP_MIB_IF_CONFIG pCurIfConfig;
|
||
|
PIGMP_MIB_SET_INPUT_DATA pSetInputData = NULL;
|
||
|
|
||
|
PIGMP_MIB_GET_OUTPUT_DATA pResponse = NULL;
|
||
|
IGMP_MIB_GET_INPUT_DATA Query;
|
||
|
|
||
|
|
||
|
BEGIN_BREAKOUT_BLOCK {
|
||
|
|
||
|
//
|
||
|
// retrieve existing interface config
|
||
|
//
|
||
|
|
||
|
dwRes = GetInterfaceInfo(MIB_ACTION_GET,
|
||
|
&IfIndex, &pResponse, CONFIG_TYPE);
|
||
|
|
||
|
if (dwRes != NO_ERROR) {
|
||
|
TraceError(dwRes);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Update fields
|
||
|
//
|
||
|
|
||
|
pCurIfConfig = (PIGMP_MIB_IF_CONFIG) pResponse->Buffer;
|
||
|
|
||
|
|
||
|
// set IfIndex
|
||
|
|
||
|
pCurIfConfig->IfIndex = IfIndex;
|
||
|
|
||
|
|
||
|
|
||
|
// update interface version
|
||
|
|
||
|
dwValue = GET_ASN_INTEGER(&pNewIfConfig->igmpInterfaceVersion, 0);
|
||
|
|
||
|
if (dwValue!=0)
|
||
|
pCurIfConfig->IgmpProtocolType = (dwValue==1)
|
||
|
? IGMP_ROUTER_V1
|
||
|
: IGMP_ROUTER_V2;
|
||
|
|
||
|
|
||
|
// update RobustnessVariable
|
||
|
|
||
|
pCurIfConfig->RobustnessVariable
|
||
|
= GET_ASN_INTEGER(&pNewIfConfig->igmpInterfaceRobustness, 0);
|
||
|
|
||
|
|
||
|
|
||
|
// calculate StartupQueryCount from RobustnessVariable
|
||
|
|
||
|
pCurIfConfig->StartupQueryCount
|
||
|
= pCurIfConfig->RobustnessVariable;
|
||
|
|
||
|
|
||
|
|
||
|
// update igmpInterfaceQueryInterval
|
||
|
|
||
|
pCurIfConfig->GenQueryInterval
|
||
|
= GET_ASN_INTEGER(&pNewIfConfig->igmpInterfaceQueryInterval, 0);
|
||
|
|
||
|
|
||
|
|
||
|
// calculate value of StartupQueryInterval from GenQueryInterval
|
||
|
|
||
|
pCurIfConfig->StartupQueryInterval
|
||
|
= (DWORD)(0.25*pCurIfConfig->GenQueryInterval);
|
||
|
|
||
|
|
||
|
|
||
|
// update GenQueryMaxResponseTime
|
||
|
|
||
|
pCurIfConfig->GenQueryMaxResponseTime
|
||
|
= GET_ASN_INTEGER(
|
||
|
&pNewIfConfig->igmpInterfaceQueryMaxResponseTime, 0
|
||
|
);
|
||
|
|
||
|
|
||
|
// update LastMemQueryInterval
|
||
|
|
||
|
pCurIfConfig->LastMemQueryInterval
|
||
|
= GET_ASN_INTEGER(
|
||
|
&pNewIfConfig->igmpInterfaceLastMembQueryInterval, 0
|
||
|
);
|
||
|
|
||
|
|
||
|
|
||
|
// calculate LastMemQueryCount from RobustnessVariable
|
||
|
|
||
|
pCurIfConfig->LastMemQueryCount = pCurIfConfig->RobustnessVariable;
|
||
|
|
||
|
|
||
|
// LeaveEnabled is not changed
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Save interface config
|
||
|
//
|
||
|
|
||
|
dwSetSize = sizeof(IGMP_MIB_SET_INPUT_DATA) - 1 +
|
||
|
sizeof(IGMP_MIB_IF_CONFIG);
|
||
|
|
||
|
pSetInputData = (PIGMP_MIB_SET_INPUT_DATA) IGMP_MIB_ALLOC(dwSetSize);
|
||
|
|
||
|
if (!pSetInputData) {
|
||
|
dwRes = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
TRACE0( " Not enough memory " );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pSetInputData->TypeId = IGMP_IF_CONFIG_ID;
|
||
|
pSetInputData->Flags = 0;
|
||
|
|
||
|
pSetInputData->BufferSize = sizeof(IGMP_MIB_IF_CONFIG);
|
||
|
|
||
|
CopyMemory(
|
||
|
pSetInputData->Buffer,
|
||
|
pCurIfConfig,
|
||
|
pSetInputData->BufferSize
|
||
|
);
|
||
|
|
||
|
|
||
|
IGMP_MIB_SET(pSetInputData, dwSetSize, dwRes);
|
||
|
|
||
|
if (dwRes!=NO_ERROR) {
|
||
|
TraceError( dwRes );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwRes = MIB_S_SUCCESS;
|
||
|
|
||
|
} END_BREAKOUT_BLOCK;
|
||
|
|
||
|
if (pResponse)
|
||
|
MprAdminMIBBufferFree(pResponse);
|
||
|
|
||
|
if (pSetInputData)
|
||
|
IGMP_MIB_FREE(pSetInputData);
|
||
|
|
||
|
|
||
|
return dwRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
UINT
|
||
|
set_igmpInterfaceEntry(
|
||
|
UINT ActionId,
|
||
|
AsnAny * ObjectArray,
|
||
|
UINT * ErrorIndex
|
||
|
)
|
||
|
{
|
||
|
DWORD dwRes = NO_ERROR;
|
||
|
|
||
|
TraceEnter("set_igmpInterfaceEntry");
|
||
|
|
||
|
switch (ActionId)
|
||
|
{
|
||
|
|
||
|
case MIB_ACTION_VALIDATE :
|
||
|
|
||
|
dwRes = ValidateInterfaceConfig(ObjectArray);
|
||
|
|
||
|
break;
|
||
|
|
||
|
|
||
|
case MIB_ACTION_SET :
|
||
|
|
||
|
dwRes = SetInterfaceConfig(ObjectArray);
|
||
|
|
||
|
break;
|
||
|
|
||
|
|
||
|
case MIB_ACTION_CLEANUP :
|
||
|
|
||
|
dwRes = MIB_S_SUCCESS;
|
||
|
|
||
|
break;
|
||
|
|
||
|
|
||
|
default :
|
||
|
|
||
|
TRACE0("set_ifConfigEntry - wrong action");
|
||
|
|
||
|
dwRes = MIB_S_INVALID_PARAMETER;
|
||
|
|
||
|
break;
|
||
|
|
||
|
} //end switch(ActionId)
|
||
|
|
||
|
|
||
|
TraceLeave("set_igmpInterfaceEntry");
|
||
|
|
||
|
return dwRes;
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
// igmpCacheEntry table (1,3,6,1,3,59,1,1,2,1) //
|
||
|
// //
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
UINT
|
||
|
get_igmpCacheEntry(
|
||
|
UINT ActionId,
|
||
|
AsnAny * ObjectArray,
|
||
|
UINT * ErrorIndex
|
||
|
)
|
||
|
{
|
||
|
DWORD dwRes = NO_ERROR;
|
||
|
PIGMP_MIB_GET_OUTPUT_DATA pResponse;
|
||
|
DWORD IfIndex, Group, ReturnedGroup, dwTmpActionId;
|
||
|
buf_igmpCacheEntry *pMibCacheEntry
|
||
|
= (buf_igmpCacheEntry*)ObjectArray;
|
||
|
PIGMP_MIB_GROUP_INFO pGIEntry;
|
||
|
PIGMP_MIB_GROUP_IFS_LIST pGroupIfsList;
|
||
|
|
||
|
|
||
|
TraceEnter("get_igmpCacheEntry");
|
||
|
|
||
|
|
||
|
// get the interface index
|
||
|
|
||
|
IfIndex = GET_ASN_INTEGER(&pMibCacheEntry->igmpCacheIfIndex, 0);
|
||
|
|
||
|
|
||
|
|
||
|
// get the group address
|
||
|
|
||
|
Group = GET_ASN_IP_ADDRESS(&pMibCacheEntry->igmpCacheAddress, 0);
|
||
|
|
||
|
|
||
|
TRACE2("get_igmpCacheEntry called with IfIndex:%d, Group:%d.%d.%d.%d",
|
||
|
IfIndex, PRINT_IPADDR(Group));
|
||
|
|
||
|
|
||
|
dwTmpActionId = ActionId;
|
||
|
|
||
|
if ( Group==0 && ActionId==MIB_ACTION_GETNEXT )
|
||
|
{
|
||
|
dwTmpActionId = MIB_ACTION_GETFIRST;
|
||
|
}
|
||
|
|
||
|
else if (ActionId==MIB_ACTION_GETNEXT)
|
||
|
{
|
||
|
dwTmpActionId = MIB_ACTION_GET;
|
||
|
}
|
||
|
|
||
|
pResponse = NULL;
|
||
|
|
||
|
while (1) {
|
||
|
|
||
|
if (pResponse)
|
||
|
MprAdminMIBBufferFree(pResponse);
|
||
|
|
||
|
TRACE2("GetCacheEntry() called for Group: %d.%d.%d.%d, If:%d",
|
||
|
PRINT_IPADDR(Group), IfIndex);
|
||
|
|
||
|
//
|
||
|
// retrieve the cache entry
|
||
|
//
|
||
|
dwRes = GetCacheEntry(
|
||
|
dwTmpActionId,
|
||
|
IfIndex,
|
||
|
Group,
|
||
|
&ReturnedGroup,
|
||
|
&pResponse
|
||
|
);
|
||
|
|
||
|
|
||
|
if (Group!=ReturnedGroup)
|
||
|
IfIndex = 0;
|
||
|
|
||
|
dwTmpActionId = MIB_ACTION_GETNEXT;
|
||
|
|
||
|
// return if error
|
||
|
|
||
|
if (dwRes!=NO_ERROR) {
|
||
|
TraceError(dwRes);
|
||
|
TraceLeave("get_igmpCacheEntry");
|
||
|
return dwRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
pGroupIfsList = (PIGMP_MIB_GROUP_IFS_LIST)pResponse->Buffer;
|
||
|
|
||
|
// no ifs for that group
|
||
|
|
||
|
if (pGroupIfsList->NumInterfaces == 0) {
|
||
|
|
||
|
// for GET return error
|
||
|
|
||
|
if (ActionId==MIB_ACTION_GET || ActionId==MIB_ACTION_GETFIRST)
|
||
|
{
|
||
|
MprAdminMIBBufferFree(pResponse);
|
||
|
return MIB_S_ENTRY_NOT_FOUND;
|
||
|
}
|
||
|
|
||
|
// for GETNEXT continue with next group
|
||
|
else
|
||
|
{
|
||
|
Group = ReturnedGroup;
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pGIEntry = (PIGMP_MIB_GROUP_INFO)pGroupIfsList->Buffer;
|
||
|
|
||
|
// if GET, then try to find the exact entry
|
||
|
|
||
|
if (ActionId==MIB_ACTION_GET)
|
||
|
{
|
||
|
DWORD i;
|
||
|
for (i=0; i<pGroupIfsList->NumInterfaces; i++,pGIEntry++)
|
||
|
{
|
||
|
if (pGIEntry->IfIndex==IfIndex)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// exact entry not found for GET
|
||
|
|
||
|
if (i==pGroupIfsList->NumInterfaces)
|
||
|
{
|
||
|
MprAdminMIBBufferFree(pResponse);
|
||
|
return MIB_S_ENTRY_NOT_FOUND;
|
||
|
}
|
||
|
}
|
||
|
else if (ActionId==MIB_ACTION_GETNEXT)
|
||
|
{
|
||
|
DWORD i;
|
||
|
PIGMP_MIB_GROUP_INFO pNextGI = pGIEntry;
|
||
|
|
||
|
for (i=0; i<pGroupIfsList->NumInterfaces; i++,pGIEntry++)
|
||
|
{
|
||
|
if (pGIEntry->IfIndex > IfIndex &&
|
||
|
pGIEntry->IfIndex < pNextGI->IfIndex)
|
||
|
{
|
||
|
pNextGI = pGIEntry;
|
||
|
}
|
||
|
}
|
||
|
if (pNextGI->IfIndex <= IfIndex)
|
||
|
{
|
||
|
Group = ReturnedGroup;
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
pGIEntry = pNextGI;
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// fill in the required fields and return the MibCacheEntry
|
||
|
//
|
||
|
Group = ReturnedGroup;
|
||
|
IfIndex = pGIEntry->IfIndex;
|
||
|
|
||
|
TRACE2("GetCacheEntry() returned for Interface: %d for group(%d.%d.%d.%d)",
|
||
|
IfIndex, PRINT_IPADDR(Group));
|
||
|
|
||
|
|
||
|
//
|
||
|
// set Group/IfIndex for following getnext operation, (if any)
|
||
|
//
|
||
|
|
||
|
FORCE_SET_ASN_IP_ADDRESS(
|
||
|
&(pMibCacheEntry->igmpCacheAddress),
|
||
|
&(pMibCacheEntry->igmpCacheAddressBuf),
|
||
|
Group
|
||
|
);
|
||
|
|
||
|
FORCE_SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheIfIndex),
|
||
|
IfIndex);
|
||
|
|
||
|
// find out if the group is added on the localhost interface
|
||
|
{
|
||
|
DWORD BufLen, Status;
|
||
|
IPAddr *pIgmpList = NULL, *pIgmpEntry;
|
||
|
|
||
|
|
||
|
// set all default values to false
|
||
|
|
||
|
SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheSelf), 2);
|
||
|
|
||
|
|
||
|
GetIgmpList(pGIEntry->IpAddr, NULL, &BufLen);
|
||
|
|
||
|
pIgmpList = HeapAlloc(GetProcessHeap(), 0, BufLen);
|
||
|
|
||
|
|
||
|
if (pIgmpList) {
|
||
|
|
||
|
Status = GetIgmpList(pGIEntry->IpAddr, pIgmpList, &BufLen);
|
||
|
|
||
|
if (Status == STATUS_SUCCESS)
|
||
|
{
|
||
|
ULONG Count = BufLen/sizeof(IPAddr);
|
||
|
ULONG i;
|
||
|
|
||
|
for (i=0,pIgmpEntry=pIgmpList; i<Count; i++,pIgmpEntry++)
|
||
|
{
|
||
|
if (*pIgmpEntry == Group) {
|
||
|
SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheSelf), 1);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HeapFree(GetProcessHeap(), 0, pIgmpList);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
SET_ASN_IP_ADDRESS(&pMibCacheEntry->igmpCacheLastReporter,
|
||
|
&pMibCacheEntry->igmpCacheLastReporterBuf,
|
||
|
pGIEntry->LastReporter);
|
||
|
|
||
|
|
||
|
// multiply GroupUpTime and GroupExpiryTime by 100 to get timeTicks
|
||
|
|
||
|
SET_ASN_TIME_TICKS(&(pMibCacheEntry->igmpCacheUpTime),
|
||
|
pGIEntry->GroupUpTime*100);
|
||
|
|
||
|
SET_ASN_TIME_TICKS(&(pMibCacheEntry->igmpCacheExpiryTime),
|
||
|
pGIEntry->GroupExpiryTime*100);
|
||
|
|
||
|
|
||
|
|
||
|
// cache status is always active(1)
|
||
|
|
||
|
SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheStatus), 1);
|
||
|
|
||
|
SET_ASN_INTEGER(&(pMibCacheEntry->igmpCacheVersion1HostTimer),
|
||
|
pGIEntry->V1HostPresentTimeLeft);
|
||
|
|
||
|
|
||
|
MprAdminMIBBufferFree(pResponse);
|
||
|
|
||
|
TraceLeave("get_igmpCacheEntry");
|
||
|
return dwRes;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
GetCacheEntry(
|
||
|
DWORD ActionId,
|
||
|
DWORD IfIndex,
|
||
|
DWORD Group,
|
||
|
DWORD *pNextGroup,
|
||
|
PIGMP_MIB_GET_OUTPUT_DATA *ppResponse
|
||
|
)
|
||
|
/*++
|
||
|
Routine Description:
|
||
|
Get the Group-Interface entry from igmp.
|
||
|
--*/
|
||
|
{
|
||
|
IGMP_MIB_GET_INPUT_DATA Query;
|
||
|
DWORD dwErr = NO_ERROR, dwOutSize;
|
||
|
|
||
|
|
||
|
*ppResponse = NULL;
|
||
|
|
||
|
ZeroMemory(&Query, sizeof(Query));
|
||
|
Query.TypeId = IGMP_GROUP_IFS_LIST_ID;
|
||
|
Query.Flags = IGMP_ENUM_ONE_ENTRY | IGMP_ENUM_ALL_INTERFACES_GROUPS;
|
||
|
Query.Count = 1;
|
||
|
Query.IfIndex = IfIndex;
|
||
|
Query.GroupAddr = Group;
|
||
|
|
||
|
|
||
|
switch (ActionId) {
|
||
|
|
||
|
//
|
||
|
// ERROR_INVALID_PARAMETER is returned when there are no
|
||
|
// interfaces with groups
|
||
|
// RPC_S_SERVER_UNAVAILABLE is returned when the router
|
||
|
// isn't running.
|
||
|
//
|
||
|
|
||
|
case MIB_ACTION_GET :
|
||
|
{
|
||
|
|
||
|
IGMP_MIB_GET(&Query, sizeof(Query), ppResponse,
|
||
|
&dwOutSize, dwErr);
|
||
|
|
||
|
if (dwErr==ERROR_INVALID_PARAMETER
|
||
|
|| dwErr==RPC_S_SERVER_UNAVAILABLE)
|
||
|
|
||
|
dwErr = MIB_S_ENTRY_NOT_FOUND;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
case MIB_ACTION_GETFIRST :
|
||
|
{
|
||
|
IGMP_MIB_GETFIRST(&Query, sizeof(Query), ppResponse,
|
||
|
&dwOutSize, dwErr);
|
||
|
|
||
|
if (dwErr==ERROR_INVALID_PARAMETER
|
||
|
|| dwErr==RPC_S_SERVER_UNAVAILABLE)
|
||
|
|
||
|
dwErr = MIB_S_NO_MORE_ENTRIES;
|
||
|
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
|
||
|
case MIB_ACTION_GETNEXT :
|
||
|
{
|
||
|
IGMP_MIB_GETNEXT(&Query, sizeof(Query), ppResponse,
|
||
|
&dwOutSize, dwErr);
|
||
|
|
||
|
if (dwErr==ERROR_INVALID_PARAMETER
|
||
|
|| dwErr==RPC_S_SERVER_UNAVAILABLE)
|
||
|
|
||
|
dwErr = MIB_S_NO_MORE_ENTRIES;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default :
|
||
|
{
|
||
|
dwErr = MIB_S_INVALID_PARAMETER;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
if (dwErr!=NO_ERROR)
|
||
|
*ppResponse = NULL;
|
||
|
|
||
|
else
|
||
|
*pNextGroup = Query.GroupAddr;
|
||
|
|
||
|
|
||
|
return dwErr;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
UINT
|
||
|
set_igmpCacheEntry(
|
||
|
UINT ActionId,
|
||
|
AsnAny * ObjectArray,
|
||
|
UINT * ErrorIndex
|
||
|
)
|
||
|
{
|
||
|
return MIB_S_NOT_SUPPORTED;
|
||
|
}
|
||
|
|
||
|
|
||
|
DWORD
|
||
|
ConnectToRouter(
|
||
|
)
|
||
|
{
|
||
|
DWORD dwRes = (DWORD) -1;
|
||
|
|
||
|
|
||
|
EnterCriticalSection( &g_CS );
|
||
|
|
||
|
do
|
||
|
{
|
||
|
MPR_SERVER_HANDLE hTmp;
|
||
|
|
||
|
if ( g_hMibServer )
|
||
|
{
|
||
|
dwRes = NO_ERROR;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dwRes = MprAdminMIBServerConnect( NULL, &hTmp );
|
||
|
|
||
|
if ( dwRes == NO_ERROR )
|
||
|
{
|
||
|
InterlockedExchangePointer(&g_hMibServer, hTmp );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TRACE1(
|
||
|
"Error %d setting up DIM connection to MIB Server\n",
|
||
|
dwRes
|
||
|
);
|
||
|
}
|
||
|
|
||
|
} while ( FALSE );
|
||
|
|
||
|
LeaveCriticalSection( &g_CS );
|
||
|
|
||
|
return dwRes;
|
||
|
}
|