windows-nt/Source/XPSP1/NT/net/rras/ip/sample/mibmgr.c
2020-09-26 16:20:57 +08:00

367 lines
11 KiB
C

/*++
Copyright (c) 1999, Microsoft Corporation
Module Name:
sample\mibmanager.c
Abstract:
The file contains IP Sample's MIB implementation.
Revision History:
MohitT June-15-1999 Created
--*/
#include "pchsample.h"
#pragma hdrstop
DWORD
WINAPI
MM_MibSet (
IN PIPSAMPLE_MIB_SET_INPUT_DATA pimsid)
/*++
Routine Description
Set IPSAMPLE's global or interface configuration.
Locks
Acquires shared (g_ce.pneNetworkEntry)->rwlLock
Releases (g_ce.pneNetworkEntry)->rwlLock
Arguments
pimsid input data, contains global/interface configuration
Return Value
NO_ERROR success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
ROUTING_PROTOCOL_EVENTS rpeEvent;
MESSAGE mMessage = {0, 0, 0};
PINTERFACE_ENTRY pie;
if (!ENTER_SAMPLE_API()) { return ERROR_CAN_NOT_COMPLETE; }
do // breakout loop
{
// set global configuration
if (pimsid->IMSID_TypeID is IPSAMPLE_GLOBAL_CONFIG_ID)
{
if (pimsid->IMSID_BufferSize < sizeof(IPSAMPLE_GLOBAL_CONFIG))
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = CM_SetGlobalInfo((PVOID) pimsid->IMSID_Buffer);
if (dwErr != NO_ERROR)
break;
rpeEvent = SAVE_GLOBAL_CONFIG_INFO;
}
// set interface configuration
else if (pimsid->IMSID_TypeID is IPSAMPLE_IF_CONFIG_ID)
{
if (pimsid->IMSID_BufferSize < sizeof(IPSAMPLE_IF_CONFIG))
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwErr = NM_SetInterfaceInfo(pimsid->IMSID_IfIndex,
(PVOID) pimsid->IMSID_Buffer);
if (dwErr != NO_ERROR)
break;
rpeEvent = SAVE_INTERFACE_CONFIG_INFO;
mMessage.InterfaceIndex = pimsid->IMSID_IfIndex;
}
// error, unexpected type
else
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
// notify router manager
if (EnqueueEvent(rpeEvent, mMessage) is NO_ERROR)
SetEvent(g_ce.hMgrNotificationEvent);
} while(FALSE);
LEAVE_SAMPLE_API();
return dwErr;
}
DWORD
WINAPI
MM_MibGet (
IN PIPSAMPLE_MIB_GET_INPUT_DATA pimgid,
OUT PIPSAMPLE_MIB_GET_OUTPUT_DATA pimgod,
IN OUT PULONG pulOutputSize,
IN MODE mMode)
/*++
Routine Description
Handles the structure accesses required to read MIB data. Supports
three modes of querying: EXACT, FIRST, and NEXT, which correspond to
MibGet(), MibGetFirst(), and MibGetNext() respectively.
Locks
Acquires shared (g_ce.pneNetworkEntry)->rwlLock
Releases (g_ce.pneNetworkEntry)->rwlLock
Arguments
pimgid input data
pimgod output buffer
pulOutputSize IN size of output buffer given
OUT size of output buffer needed
mMode query type
Return Value
NO_ERROR success
Error Code o/w
--*/
{
DWORD dwErr = NO_ERROR;
ULONG ulSizeGiven = 0;
ULONG ulSizeNeeded = 0;
PINTERFACE_ENTRY pie;
if (!ENTER_SAMPLE_API()) { return ERROR_CAN_NOT_COMPLETE; }
// compute the size of the buffer available for storing
// returned structures (the size of IMGOD_Buffer)
if (*pulOutputSize < sizeof(IPSAMPLE_MIB_GET_OUTPUT_DATA))
ulSizeGiven = 0;
else
ulSizeGiven = *pulOutputSize - sizeof(IPSAMPLE_MIB_GET_OUTPUT_DATA);
switch (pimgid->IMGID_TypeID)
{
// the global statistics struct is fixed-length.
// there is a single instance.
case IPSAMPLE_GLOBAL_STATS_ID:
{
PIPSAMPLE_GLOBAL_STATS pigsdst, pigssrc;
// only GET_EXACT and GET_FIRST are valid for the
// global stats object since there is only one entry
if (mMode is GET_NEXT)
{
dwErr = ERROR_NO_MORE_ITEMS;
break;
}
// set the output size required for this entry
ulSizeNeeded = sizeof(IPSAMPLE_GLOBAL_STATS);
// check that the output buffer is big enough
if (ulSizeGiven < ulSizeNeeded)
{
dwErr = ERROR_INSUFFICIENT_BUFFER;
break;
}
pimgod->IMGOD_TypeID = IPSAMPLE_GLOBAL_STATS_ID;
// since access to this structure is synchronized through
// locked increments/decrements, we must copy it field by field
pigssrc = &(g_ce.igsStats);
pigsdst = (PIPSAMPLE_GLOBAL_STATS) pimgod->IMGOD_Buffer;
pigsdst->ulNumInterfaces = pigssrc->ulNumInterfaces;
break;
}
// the global configuration structure may be of variable size.
// there is a single instance.
case IPSAMPLE_GLOBAL_CONFIG_ID:
{
// only GET_EXACT and GET_FIRST are valid for the
// global configuration object since there is only one entry
if (mMode is GET_NEXT)
{
dwErr = ERROR_NO_MORE_ITEMS;
break;
}
// CM_GetGlobalInfo() decides whether the buffer size is
// sufficient. if so, it retrieves the global configuration.
// either case it sets the required output buffer size.
dwErr = CM_GetGlobalInfo ((PVOID) pimgod->IMGOD_Buffer,
&ulSizeGiven,
NULL,
NULL,
NULL);
ulSizeNeeded = ulSizeGiven;
// check that the output buffer was big enough
if (dwErr != NO_ERROR)
break;
pimgod->IMGOD_TypeID = IPSAMPLE_GLOBAL_CONFIG_ID;
break;
}
// the interface statistics struct is fixed-length.
// there may be multiple instances.
case IPSAMPLE_IF_STATS_ID:
{
PIPSAMPLE_IF_STATS piisdst, piissrc;
ACQUIRE_READ_LOCK(&(g_ce.pneNetworkEntry)->rwlLock);
do // breakout loop
{
// retrieve the interface whose stats are to be read
dwErr = IE_GetIndex(pimgid->IMGID_IfIndex,
mMode,
&pie);
if (dwErr != NO_ERROR)
break;
// set the output size required for this entry
ulSizeNeeded = sizeof(IPSAMPLE_IF_STATS);
// check that the output buffer is big enough
if (ulSizeGiven < ulSizeNeeded)
{
dwErr = ERROR_INSUFFICIENT_BUFFER;
break;
}
pimgod->IMGOD_TypeID = IPSAMPLE_IF_STATS_ID;
pimgod->IMGOD_IfIndex = pie->dwIfIndex;
// access to this structure is synchronized through locked
// increments/decrements, so we copy it field by field
piissrc = &(pie->iisStats);
piisdst = (PIPSAMPLE_IF_STATS) pimgod->IMGOD_Buffer;
piisdst->ulNumPackets = piissrc->ulNumPackets;
} while (FALSE);
RELEASE_READ_LOCK(&(g_ce.pneNetworkEntry)->rwlLock);
break;
}
// the interface configuration structure may be of variable size.
// there may be multiple instances.
case IPSAMPLE_IF_CONFIG_ID:
{
// get the queried interface's index
ACQUIRE_READ_LOCK(&(g_ce.pneNetworkEntry)->rwlLock);
do // breakout loop
{
dwErr = IE_GetIndex(pimgid->IMGID_IfIndex,
mMode,
&pie);
if (dwErr != NO_ERROR)
break;
// read lock acuired again, which is fine :)
dwErr = NM_GetInterfaceInfo(pie->dwIfIndex,
(PVOID) pimgod->IMGOD_Buffer,
&ulSizeGiven,
NULL,
NULL,
NULL);
ulSizeNeeded = ulSizeGiven;
// check that the output buffer was big enough
if (dwErr != NO_ERROR)
break;
pimgod->IMGOD_TypeID = IPSAMPLE_IF_CONFIG_ID;
pimgod->IMGOD_IfIndex = pie->dwIfIndex;
} while (FALSE);
RELEASE_READ_LOCK(&(g_ce.pneNetworkEntry)->rwlLock);
break;
}
// the interface binding structure is of variable size.
// there may be multiple instances.
case IPSAMPLE_IF_BINDING_ID:
{
PIPSAMPLE_IF_BINDING piib;
PIPSAMPLE_IP_ADDRESS piia;
ACQUIRE_READ_LOCK(&(g_ce.pneNetworkEntry)->rwlLock);
do // breakout loop
{
// retrieve the interface whose stats are to be read
dwErr = IE_GetIndex(pimgid->IMGID_IfIndex,
mMode,
&pie);
if (dwErr != NO_ERROR)
break;
// set the output size required for this entry
ulSizeNeeded = sizeof(IPSAMPLE_IF_BINDING) +
pie->ulNumBindings * sizeof(IPSAMPLE_IP_ADDRESS);
// check that the output buffer is big enough
if (ulSizeGiven < ulSizeNeeded)
{
dwErr = ERROR_INSUFFICIENT_BUFFER;
break;
}
pimgod->IMGOD_TypeID = IPSAMPLE_IF_BINDING_ID;
pimgod->IMGOD_IfIndex = pie->dwIfIndex;
piib = (PIPSAMPLE_IF_BINDING) pimgod->IMGOD_Buffer;
piia = IPSAMPLE_IF_ADDRESS_TABLE(piib);
if (INTERFACE_IS_ACTIVE(pie))
piib->dwState |= IPSAMPLE_STATE_ACTIVE;
if (INTERFACE_IS_BOUND(pie))
piib->dwState |= IPSAMPLE_STATE_BOUND;
piib->ulCount = pie->ulNumBindings;
CopyMemory((PVOID) piia, // address,mask pairs
(PVOID) pie->pbeBindingTable, // ditto
pie->ulNumBindings * sizeof(IPSAMPLE_IP_ADDRESS));
} while (FALSE);
RELEASE_READ_LOCK(&(g_ce.pneNetworkEntry)->rwlLock);
break;
}
default:
{
dwErr = ERROR_INVALID_PARAMETER;
break;
}
}
*pulOutputSize = sizeof(IPSAMPLE_MIB_GET_OUTPUT_DATA) + ulSizeNeeded;
LEAVE_SAMPLE_API();
return dwErr;
}