/*++ 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; }