/*++ Copyright (c) 1998 Microsoft Corporation Module Name: routing\ip\mcastmib\mibfuncs.c Abstract: IP Multicast MIB instrumentation callbacks Revision history: Dave Thaler 4/17/98 Created --*/ #include "precomp.h" #pragma hdrstop // // Define this to report a dummy MFE // #undef SAMPLE_MFE #define ROWSTATUS_ACTIVE 1 DWORD ConnectToRouter(); DWORD SetGlobalInfo( IN AsnAny * objectArray ); DWORD GetMibInfo( IN UINT actionId, IN PMIB_OPAQUE_QUERY pQuery, IN DWORD dwQuerySize, OUT PMIB_OPAQUE_INFO * ppimgod, OUT PDWORD pdwOutSize ); // // IP Multicast MIB scalar objects // UINT get_global( UINT actionId, AsnAny *objectArray, UINT *errorIndex ) { DWORD dwErr = ERROR_NOT_FOUND; DWORD dwNumEntries = 1; PMIB_IPMCAST_GLOBAL pEntry; buf_global *pOutput; PMIB_OPAQUE_INFO pRpcInfo = NULL; DWORD dwOutBufferSize = 0; MIB_OPAQUE_QUERY pQueryBuff, *pQuery = &pQueryBuff; DWORD dwQuerySize; TraceEnter("get_global"); pOutput = (buf_global*)objectArray; pQuery->dwVarId = MCAST_GLOBAL; dwQuerySize = sizeof(MIB_OPAQUE_QUERY) - sizeof(DWORD); dwErr = GetMibInfo(actionId, pQuery, dwQuerySize, &pRpcInfo, &dwOutBufferSize); if (dwErr != NO_ERROR) { TraceError(dwErr); return dwErr; } pEntry = (PMIB_IPMCAST_GLOBAL) pRpcInfo->rgbyData; SetAsnInteger(&(pOutput->ipMRouteEnable), pEntry->dwEnable); if (pRpcInfo) MprAdminMIBBufferFree(pRpcInfo); TraceLeave("get_global"); return MIB_S_SUCCESS; } // // IP Multicast Interface Table support // // We cache the fields which are static config info (such as protocol) // so that queries that access only these rows can consult the cache // rather than forcing a call to the router manager, kernel diving, etc. // typedef struct { DWORD dwIfIndex; // interface to which this info applies DWORD dwProtocol; // multicast protocol owning that interface DWORD dwTimestamp; // time at which above info was obtained } MCAST_IF_CONFIG; #define CACHE_SIZE 100 // number of interfaces to cache MCAST_IF_CONFIG *cacheArray[CACHE_SIZE]; static int GetCacheIdx(dwIfIndex) DWORD dwIfIndex; { register int i; for (i=0; idwIfIndex==dwIfIndex) return i; return -1; } static void UpdateCacheInterfaceConfig(dwCacheIdx, newIfConfig) DWORD dwCacheIdx; MCAST_IF_CONFIG *newIfConfig; { // Free the old one if (cacheArray[dwCacheIdx]) MULTICAST_MIB_FREE( cacheArray[dwCacheIdx] ); // Store the new one cacheArray[dwCacheIdx] = newIfConfig; } static void AddCacheInterfaceConfig(pIfConfig) MCAST_IF_CONFIG *pIfConfig; { register int i, best = -1; // Find empty or oldest spot for (i=0; idwTimestamp < cacheArray[best]->dwTimestamp) best=i; } UpdateCacheInterfaceConfig(best, pIfConfig); } static MCAST_IF_CONFIG * SaveInterfaceConfig(pEntry) PMIB_IPMCAST_IF_ENTRY pEntry; { MCAST_IF_CONFIG *pIfConfig; int iCacheIdx; TRACE1("SaveInterfaceConfig %d\n", pEntry->dwIfIndex); pIfConfig= MULTICAST_MIB_ALLOC(sizeof(MCAST_IF_CONFIG)); if (!pIfConfig) { return NULL; } pIfConfig->dwIfIndex = pEntry->dwIfIndex; pIfConfig->dwProtocol = pEntry->dwProtocol; pIfConfig->dwTimestamp = GetCurrentTime(); iCacheIdx = GetCacheIdx(pEntry->dwIfIndex); if (iCacheIdx >= 0) UpdateCacheInterfaceConfig((DWORD)iCacheIdx, pIfConfig); else AddCacheInterfaceConfig(pIfConfig); return pIfConfig; } MCAST_IF_CONFIG * GetInterfaceConfig(dwIfIndex) DWORD dwIfIndex; { MCAST_IF_CONFIG *outIfConfig = NULL; MCAST_IF_CONFIG *pIfConfig; DWORD dwQuerySize; MIB_OPAQUE_QUERY pQueryBuff, *pQuery = &pQueryBuff; DWORD dwErr = ERROR_NOT_FOUND; DWORD dwNumEntries = 1; PMIB_IPMCAST_IF_ENTRY pEntry; buf_ipMRouteInterfaceEntry *pOutput; PMIB_OPAQUE_INFO pRpcInfo = NULL; DWORD dwOutBufferSize = 0; TRACE1("GetInterfaceConfig %d\n", dwIfIndex); // Do a MIB lookup pQuery->dwVarId = MCAST_IF_ENTRY; pQuery->rgdwVarIndex[0] = dwIfIndex; dwQuerySize = sizeof(MIB_OPAQUE_QUERY); dwErr = GetMibInfo(MIB_ACTION_GET, pQuery, dwQuerySize, &pRpcInfo, &dwOutBufferSize); // Save each entry returned if (dwErr == NO_ERROR) { pEntry = (PMIB_IPMCAST_IF_ENTRY) pRpcInfo->rgbyData; pIfConfig = SaveInterfaceConfig(pEntry); if (pEntry->dwIfIndex == dwIfIndex) outIfConfig = pIfConfig; } // Return the saved entry which was asked for if (pRpcInfo) MprAdminMIBBufferFree(pRpcInfo); return outIfConfig; } MCAST_IF_CONFIG * ForceGetCacheInterfaceConfig(dwIfIndex) DWORD dwIfIndex; { MCAST_IF_CONFIG *tmpIfConfig; int iCacheIdx = GetCacheIdx(dwIfIndex); TRACE2("ForceGetCacheInterfaceConfig ifIndex=%d ci=%d\n", dwIfIndex, iCacheIdx); if (iCacheIdx >= 0 && GetCurrentTime() - cacheArray[iCacheIdx]->dwTimestamp < IPMULTI_IF_CACHE_TIMEOUT) return cacheArray[iCacheIdx]; // Service a cache miss tmpIfConfig = GetInterfaceConfig(dwIfIndex); return tmpIfConfig; } static DWORD GetInterfaceProtocol(dwIfIndex) DWORD dwIfIndex; { // Look up interface config in interface config cache MCAST_IF_CONFIG *pIfConfig = ForceGetCacheInterfaceConfig(dwIfIndex); return (pIfConfig)? pIfConfig->dwProtocol : 0; } UINT get_ipMRouteInterfaceEntry( UINT actionId, AsnAny * objectArray, UINT * errorIndex ) /*++ Routine Description: Get the InterfaceEntry for IP Multicast. Have to get the InterfaceConfig and InterfaceStats for the interface from the router. --*/ { DWORD dwErr = ERROR_NOT_FOUND; DWORD dwNumEntries = 1; PMIB_IPMCAST_IF_ENTRY pEntry; buf_ipMRouteInterfaceEntry *pOutput; PMIB_OPAQUE_INFO pRpcInfo = NULL; DWORD dwOutBufferSize = 0; MIB_OPAQUE_QUERY pQueryBuff, *pQuery = &pQueryBuff; DWORD dwQuerySize; TraceEnter("get_ipMRouteInterfaceEntry"); pOutput = (buf_ipMRouteInterfaceEntry*)objectArray; pQuery->dwVarId = MCAST_IF_ENTRY; pQuery->rgdwVarIndex[0] = GetAsnInteger( &( pOutput->ipMRouteInterfaceIfIndex ), 0 ); dwQuerySize = sizeof(MIB_OPAQUE_QUERY); dwErr = GetMibInfo(actionId, pQuery, dwQuerySize, &pRpcInfo, &dwOutBufferSize); if (dwErr != NO_ERROR) { TraceError(dwErr); return ERROR_NO_MORE_ITEMS; } pEntry = (PMIB_IPMCAST_IF_ENTRY) pRpcInfo->rgbyData; SaveInterfaceConfig(pEntry); // Set index values ForceSetAsnInteger(&(pOutput->ipMRouteInterfaceIfIndex), pEntry->dwIfIndex); // Set other values SetAsnInteger(&(pOutput->ipMRouteInterfaceTtl), pEntry->dwTtl); SetAsnInteger(&(pOutput->ipMRouteInterfaceProtocol), pEntry->dwProtocol); SetAsnInteger(&(pOutput->ipMRouteInterfaceRateLimit), pEntry->dwRateLimit); SetAsnCounter(&(pOutput->ipMRouteInterfaceInMcastOctets), pEntry->ulInMcastOctets); SetAsnCounter(&(pOutput->ipMRouteInterfaceOutMcastOctets), pEntry->ulOutMcastOctets); if (pRpcInfo) MprAdminMIBBufferFree(pRpcInfo); TraceLeave("get_ipMRouteInterfaceEntry"); return MIB_S_SUCCESS; } // // Multicast Forwarding Table (ipMRouteTable) support // UINT get_ipMRouteEntry( UINT actionId, AsnAny * objectArray, UINT * errorIndex ) /*++ Routine Description: Get the MFE information based on the input criteria. --*/ { DWORD dwResult = ERROR_NOT_FOUND; DWORD dwNumEntries = 1; IPMCAST_MFE mfe; IPMCAST_MFE_STATS mfeStats; #ifdef SAMPLE_MFE MIB_IPMCAST_MFE_STATS sampledata; #endif PMIB_IPMCAST_MFE_STATS pEntry; PMIB_MFE_STATS_TABLE pTable = NULL; PMIB_OPAQUE_INFO pRpcInfo = NULL; DWORD dwOutBufferSize = 0; buf_ipMRouteEntry *pOutput; MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index // fields, so we don't have to malloc MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0]; DWORD dwQuerySize; BOOL bPart; TraceEnter("get_ipMRouteEntry"); pOutput = (buf_ipMRouteEntry*)objectArray; pQuery->dwVarId = MCAST_MFE_STATS; // Extract the instance info pQuery->rgdwVarIndex[0] = GetAsnIPAddress( &pOutput->ipMRouteGroup, 0 ); pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &pOutput->ipMRouteSource, 0xFFFFFFFF ); pQuery->rgdwVarIndex[2] = GetAsnIPAddress( &pOutput->ipMRouteSourceMask, 0xFFFFFFFF); // // Fix up query if instance was partially-specified. // This section can go away if the SNMP API does this for us. // if (!pOutput->ipMRouteGroup.asnType || !pOutput->ipMRouteGroup.asnValue.string.length) { actionId = MIB_ACTION_GETFIRST; } else { if (!pOutput->ipMRouteSource.asnType || !pOutput->ipMRouteSource.asnValue.string.length) { if (pQuery->rgdwVarIndex[0]) { pQuery->rgdwVarIndex[0]--; } else { actionId = MIB_ACTION_GETFIRST; } } else { if (!pOutput->ipMRouteSourceMask.asnType || !pOutput->ipMRouteSourceMask.asnValue.string.length) { if (pQuery->rgdwVarIndex[1]) { pQuery->rgdwVarIndex[1]--; } else { if (pQuery->rgdwVarIndex[0]) { pQuery->rgdwVarIndex[0]--; pQuery->rgdwVarIndex[1] = 0xFFFFFFFF; } else { actionId = MIB_ACTION_GETFIRST; } } } } } dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + 2*sizeof(DWORD); #ifndef SAMPLE_MFE dwResult = GetMibInfo(actionId, pQuery, dwQuerySize, &pRpcInfo, &dwOutBufferSize); if (dwResult != NO_ERROR) { TraceError(dwResult); return dwResult; } pTable = (PMIB_MFE_STATS_TABLE)( pRpcInfo->rgbyData); if (pTable->dwNumEntries == 0) { MprAdminMIBBufferFree( pRpcInfo ); return MIB_S_NO_MORE_ENTRIES; } pEntry = pTable->table; // use first entry returned #else pEntry = &sampledata; if (pQuery->rgdwVarIndex[0] >= 0x01010101) return MIB_S_NO_MORE_ENTRIES; sampledata.dwGroup = 0x01010101; /* (*,G) Entry */ sampledata.dwSource = 0x00000000; sampledata.dwSrcMask = 0x00000000; // don't care what the other values are for this test #endif // Save index terms ForceSetAsnIPAddress(&(pOutput->ipMRouteGroup), &(pOutput->dwIpMRouteGroupInfo), pEntry->dwGroup); ForceSetAsnIPAddress(&(pOutput->ipMRouteSource), &(pOutput->dwIpMRouteSourceInfo), pEntry->dwSource); ForceSetAsnIPAddress(&(pOutput->ipMRouteSourceMask), &(pOutput->dwIpMRouteSourceMaskInfo), pEntry->dwSrcMask); // Save other terms SetAsnIPAddress(&pOutput->ipMRouteUpstreamNeighbor, &pOutput->dwIpMRouteUpstreamNeighborInfo, pEntry->dwUpStrmNgbr); SetAsnInteger(&(pOutput->ipMRouteInIfIndex), pEntry->dwInIfIndex); SetAsnTimeTicks(&(pOutput->ipMRouteUpTime), pEntry->ulUpTime); SetAsnTimeTicks(&(pOutput->ipMRouteExpiryTime), pEntry->ulExpiryTime); SetAsnCounter(&(pOutput->ipMRoutePkts), pEntry->ulInPkts); SetAsnCounter(&(pOutput->ipMRouteDifferentInIfPackets), pEntry->ulPktsDifferentIf); SetAsnCounter(&(pOutput->ipMRouteOctets), pEntry->ulInOctets); // For protocol, we'll just report the protocol owning the iif SetAsnInteger(&(pOutput->ipMRouteProtocol), GetInterfaceProtocol(pEntry->dwInIfIndex)); SetAsnInteger(&pOutput->ipMRouteRtProto, pEntry->dwRouteProtocol); SetAsnIPAddress(&pOutput->ipMRouteRtAddress, &pOutput->dwIpMRouteRtAddressInfo, pEntry->dwRouteNetwork); SetAsnIPAddress(&pOutput->ipMRouteRtMask, &pOutput->dwIpMRouteRtMaskInfo, pEntry->dwRouteMask); if ( pRpcInfo ) { MprAdminMIBBufferFree( pRpcInfo ); } TraceLeave("get_ipMRouteEntry"); return MIB_S_SUCCESS; } // // Multicast Forwarding Next Hop table (ipMRouteNextHopTable) support // static DWORD LocateMfeOif(actionId, pQuery, oifIndex, oifAddress, ppEntry, ppOif, ppRpcInfo) UINT actionId; MIB_OPAQUE_QUERY *pQuery; DWORD oifIndex; DWORD oifAddress; PMIB_IPMCAST_MFE_STATS *ppEntry; PMIB_IPMCAST_OIF_STATS *ppOif; PMIB_OPAQUE_INFO *ppRpcInfo; /*++ Routine Description: Get the exact/next/first oif entry based on the input criteria. --*/ { DWORD dwResult = MIB_S_SUCCESS; DWORD dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + 2*sizeof(DWORD); DWORD dwOutBufferSize = 0; PMIB_MFE_STATS_TABLE pTable = NULL; PMIB_IPMCAST_MFE_STATS pEntry = NULL; PMIB_IPMCAST_OIF_STATS pOif = NULL; PMIB_OPAQUE_INFO pRpcInfo = NULL; BOOL oifIndexAny = FALSE; BOOL oifAddressAny = FALSE; DWORD idx; BOOL bFound; do { // Get the first MFE which applies (if any) dwResult = GetMibInfo(actionId, pQuery, dwQuerySize, &pRpcInfo, &dwOutBufferSize); if (dwResult != NO_ERROR) { TraceError(dwResult); return dwResult; } pTable = (PMIB_MFE_STATS_TABLE)( pRpcInfo->rgbyData); if (pTable->dwNumEntries == 0) { MprAdminMIBBufferFree( pRpcInfo ); return MIB_S_NO_MORE_ENTRIES; } pEntry = pTable->table; // use first entry returned // Get the first OIF which applies (if any) bFound=FALSE; for (idx=0; !bFound && idx < pEntry->ulNumOutIf; idx++) { pOif = &pEntry->rgmiosOutStats[idx]; // Do processing for GET if (actionId==MIB_ACTION_GET) { if (oifIndex == pOif->dwOutIfIndex && oifAddress == pOif->dwNextHopAddr) { bFound=TRUE; break; } else continue; } // Do processing for GET-NEXT if ( oifIndexAny == TRUE || oifIndex < pOif->dwOutIfIndex || (oifIndex == pOif->dwOutIfIndex && (oifAddressAny == TRUE || oifAddress < pOif->dwNextHopAddr))) { bFound=TRUE; break; } } if (bFound) break; // else continue and get a new entry pQuery->rgdwVarIndex[0] = pEntry->dwGroup; pQuery->rgdwVarIndex[1] = pEntry->dwSource; pQuery->rgdwVarIndex[2] = pEntry->dwSrcMask; oifAddressAny = oifIndexAny = TRUE; MprAdminMIBBufferFree( pRpcInfo ); } while (actionId != MIB_ACTION_GET); // once for GET, "forever" for others *ppEntry = pEntry; *ppOif = pOif; *ppRpcInfo = pRpcInfo; return dwResult; } UINT get_ipMRouteNextHopEntry( UINT actionId, AsnAny * objectArray, UINT * errorIndex ) { DWORD dwResult = ERROR_NOT_FOUND; DWORD dwNumEntries = 1; IPMCAST_MFE mfe; IPMCAST_MFE_STATS mfeStats; #ifdef SAMPLE_MFE MIB_IPMCAST_MFE_STATS sampledata; #endif PMIB_IPMCAST_MFE_STATS pEntry; PMIB_IPMCAST_OIF_STATS pOif; PMIB_MFE_STATS_TABLE pTable = NULL; DWORD dwOutBufferSize = 0; buf_ipMRouteNextHopEntry *pOutput; MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index // fields, so we don't have to malloc MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0]; DWORD dwQuerySize; DWORD oifIndex, oifAddress; PMIB_OPAQUE_INFO pRpcInfo = NULL; TraceEnter("get_ipMRouteNextHopEntry"); pOutput = (buf_ipMRouteNextHopEntry*)objectArray; pQuery->dwVarId = MCAST_MFE_STATS; // // XXX Note that the 3 lines below aren't quite right, since // 0-value instances will be missed. That is (*,G) entries // will be skipped!! // // Should call for a GET-FIRST if an incomplete length is given. // Maybe the Sfx API does this already. // // XXX hold off on changing this until Florin changes the SNMP // api to cover the out-of-range index case. // pQuery->rgdwVarIndex[0] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopGroup ), 0 ); pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopSource), 0 ); pQuery->rgdwVarIndex[2] = GetAsnIPAddress( &( pOutput->ipMRouteNextHopSourceMask ), 0 ); oifIndex = GetAsnInteger( &(pOutput->ipMRouteNextHopIfIndex), 0); oifAddress = GetAsnIPAddress( &(pOutput->ipMRouteNextHopAddress), 0); #ifndef SAMPLE_MFE { dwResult = LocateMfeOif(actionId, pQuery, oifIndex, oifAddress, &pEntry, &pOif, &pRpcInfo); if (dwResult != NO_ERROR) { TraceError(dwResult); return dwResult; } } #else { pEntry = &sampledata; pOif = &pEntry->rgmiosOutStats[0]; if (pQuery->rgdwVarIndex[0] >= 0x01010101) return MIB_S_NO_MORE_ENTRIES; pEntry->dwGroup = 0x01010101; pEntry->dwSource = 0x02020202; pEntry->dwSrcMask = 0x03030303; pEntry->ulNumOutIf = 1; pOif->dwOutIfIndex = 11; pOif->dwNextHopAddr = 0x04040404; pOif->ulOutPackets = 22; // don't care what the other values are for this test } #endif // Save index terms ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopGroup), &(pOutput->dwIpMRouteNextHopGroupInfo), pEntry->dwGroup); ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopSource), &(pOutput->dwIpMRouteNextHopSourceInfo), pEntry->dwSource); ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopSourceMask), &(pOutput->dwIpMRouteNextHopSourceMaskInfo), pEntry->dwSrcMask); ForceSetAsnInteger (&(pOutput->ipMRouteNextHopIfIndex), pOif->dwOutIfIndex); ForceSetAsnIPAddress(&(pOutput->ipMRouteNextHopAddress), &(pOutput->dwIpMRouteNextHopAddressInfo), pOif->dwNextHopAddr); // Save other terms SetAsnInteger(&(pOutput->ipMRouteNextHopState), 2); // "forwarding" SetAsnTimeTicks(&(pOutput->ipMRouteNextHopUpTime), pEntry->ulUpTime); // XXX SetAsnTimeTicks(&(pOutput->ipMRouteNextHopExpiryTime), pEntry->ulExpiryTime); // XXX #ifdef CLOSEST_MEMBER_HOPS SetAsnInteger(&(pOutput->ipMRouteNextHopClosestMemberHops), 1); #endif SetAsnCounter(&(pOutput->ipMRouteNextHopPkts), pOif->ulOutPackets); // For protocol, we'll just report the protocol owning the interface SetAsnInteger(&(pOutput->ipMRouteNextHopProtocol), GetInterfaceProtocol(pOif->dwOutIfIndex)); if ( pRpcInfo ) { MprAdminMIBBufferFree( pRpcInfo ); } TraceLeave("get_ipMRouteNextHopEntry"); return MIB_S_SUCCESS; } DWORD SetMibInfo( IN UINT actionId, // SET, CLEANUP IN PMIB_OPAQUE_INFO pInfo, // value info IN DWORD dwInfoSize // size of above ) { DWORD dwRes = NO_ERROR; switch ( actionId ) { #ifdef THREE_PHASE case MIB_ACTION_VALIDATE : MULTICAST_MIB_VALIDATE( pInfo, dwInfoSize, dwRes ); // ERROR_INVALID_PARAMETER is returned when there is // no interface for the specified index. // if ( dwRes == ERROR_INVALID_PARAMETER ) { dwRes = MIB_S_INVALID_PARAMETER; } break; #endif case MIB_ACTION_SET : #if 1 dwRes = ( g_hMIBServer ) ? NO_ERROR : ConnectToRouter(); if ( dwRes == NO_ERROR ) { dwRes = MprAdminMIBEntrySet( g_hMIBServer, PID_IP, IPRTRMGR_PID, (LPVOID) (pInfo), (dwInfoSize) ); } #else MULTICAST_MIB_COMMIT( pInfo, dwInfoSize, dwRes ); #endif // ERROR_INVALID_PARAMETER is returned when there is // no interface for the specified index. // if ( dwRes == ERROR_INVALID_PARAMETER || dwRes == ERROR_INVALID_INDEX ) { dwRes = MIB_S_INVALID_PARAMETER; } break; #ifdef THREE_PHASE case MIB_ACTION_CLEANUP : MULTICAST_MIB_CLEANUP( pInfo, dwInfoSize, dwRes ); // ERROR_INVALID_PARAMETER is returned when there is // no interface for the specified index. // if ( dwRes == ERROR_INVALID_PARAMETER ) { dwRes = MIB_S_INVALID_PARAMETER; } break; #endif default : dwRes = MIB_S_INVALID_PARAMETER; break; } return dwRes; } DWORD GetMibInfo( IN UINT actionId, // GET, GET-NEXT, SET IN PMIB_OPAQUE_QUERY pQuery, // instance info IN DWORD dwQuerySize, // size of above OUT PMIB_OPAQUE_INFO *ppimgod, // value info OUT PDWORD pdwOutSize // size of above ) { DWORD dwRes = (DWORD) -1; PMIB_OPAQUE_INFO pimgodOutData = NULL; *ppimgod = NULL; switch ( actionId ) { case MIB_ACTION_GET : MULTICAST_MIB_GET( pQuery, dwQuerySize, &pimgodOutData, pdwOutSize, dwRes ); // // ERROR_INVALID_PARAMETER is returned when there is // no interface for the specified index. // RPC_S_SERVER_UNAVAILABLE is returned when the router // isn't running. // if ( dwRes == ERROR_INVALID_PARAMETER || dwRes == RPC_S_SERVER_UNAVAILABLE || dwRes == RPC_S_UNKNOWN_IF ) { dwRes = MIB_S_ENTRY_NOT_FOUND; } break; case MIB_ACTION_GETFIRST : MULTICAST_MIB_GETFIRST( pQuery, dwQuerySize, &pimgodOutData, pdwOutSize, dwRes ); // // ERROR_INVALID_PARAMETER is returned when there is // no interface for the specified index. // RPC_S_SERVER_UNAVAILABLE is returned when the router // isn't running. // if ( dwRes == ERROR_INVALID_PARAMETER || dwRes == RPC_S_SERVER_UNAVAILABLE || dwRes == RPC_S_UNKNOWN_IF ) { dwRes = MIB_S_NO_MORE_ENTRIES; } break; case MIB_ACTION_GETNEXT : MULTICAST_MIB_GETNEXT( pQuery, dwQuerySize, &pimgodOutData, pdwOutSize, dwRes ); // // ERROR_INVALID_PARAMETER is returned when there is // no interface for the specified index. // RPC_S_SERVER_UNAVAILABLE is returned when the router // isn't running. // if ( dwRes == ERROR_INVALID_PARAMETER || dwRes == ERROR_NO_MORE_ITEMS || dwRes == RPC_S_SERVER_UNAVAILABLE || dwRes == RPC_S_UNKNOWN_IF ) { dwRes = MIB_S_NO_MORE_ENTRIES; break; } // // Get Next wraps to the next table at the end of the // entries in the current table. To flag the end of a table, // check the end of the table. // if ( pQuery->dwVarId != pQuery->dwVarId ) { dwRes = MIB_S_NO_MORE_ENTRIES; } break; default : dwRes = MIB_S_INVALID_PARAMETER; break; } if ( dwRes == NO_ERROR ) { *ppimgod = pimgodOutData; } else if ( pimgodOutData ) { MprAdminMIBBufferFree( pimgodOutData ); } return dwRes; } UINT set_ipMRouteScopeEntry( UINT actionId, AsnAny * objectArray, UINT * errorIndex ) { DWORD dwRes = MIB_S_SUCCESS; DWORD dwNumEntries = 1; PMIB_IPMCAST_SCOPE pEntry; sav_ipMRouteScopeEntry *pOutput; PMIB_OPAQUE_INFO pRpcInfo = NULL; DWORD dwOutBufferSize = 0; MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index // fields, so we don't have to malloc MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0]; DWORD dwQuerySize; DWORD dwIfIndex; DWORD dwAddr; DWORD dwMask; TraceEnter("set_ipMRouteScopeEntry"); pOutput = (sav_ipMRouteScopeEntry*)objectArray; dwAddr = GetAsnIPAddress( &pOutput->ipMRouteScopeAddress, 0 ); dwMask = GetAsnIPAddress( &pOutput->ipMRouteScopeAddressMask, 0 ); switch(actionId) { case MIB_ACTION_VALIDATE: // // Verify that the specified ifIndex, address, and mask are valid. // if ((dwAddr & dwMask) != dwAddr) { TRACE0( "set_ipMRouteScopeEntry: address/mask mismatch" ); dwRes = MIB_S_INVALID_PARAMETER; } else if (!IN_MULTICAST(ntohl(dwAddr))) { TRACE0( "set_ipMRouteScopeEntry: non-multicast address" ); dwRes = MIB_S_INVALID_PARAMETER; } break; case MIB_ACTION_SET: { BYTE pScopeName[MAX_SCOPE_NAME_LEN+1]; DWORD dwInfoSize; MIB_IPMCAST_SCOPE pScopeBuff[2]; // big enough to hold 1 + mib hdr // so we don't have to malloc MIB_OPAQUE_INFO *pInfo = (PMIB_OPAQUE_INFO)&pScopeBuff[0]; PMIB_IPMCAST_SCOPE pScope = (MIB_IPMCAST_SCOPE *)(pInfo->rgbyData); pInfo->dwId = MCAST_SCOPE; pScope->dwGroupAddress = dwAddr; pScope->dwGroupMask = dwMask; // // Copy the scope name. // pScopeName[0] = '\0'; GetAsnOctetString( pScopeName, &pOutput->ipMRouteScopeName ); MultiByteToWideChar( CP_UTF8, 0, pScopeName, strlen(pScopeName), pScope->snNameBuffer, MAX_SCOPE_NAME_LEN+1 ); pScope->dwStatus = GetAsnInteger( &pOutput->ipMRouteScopeStatus, 0 ); dwInfoSize = MIB_INFO_SIZE(MIB_IPMCAST_SCOPE); // // Passing a name of "" or a status of 0 tells the router // not to change the existing value. // dwRes = SetMibInfo(actionId, pInfo, dwInfoSize); break; } case MIB_ACTION_CLEANUP: dwRes = MIB_S_SUCCESS; break; default: dwRes = MIB_S_INVALID_PARAMETER; TRACE0(" set_ipMRouteScopeEntry - Wrong Action "); break; } TraceLeave("set_ipMRouteScopeEntry"); return dwRes; } UINT set_ipMRouteBoundaryEntry( UINT actionId, AsnAny * objectArray, UINT * errorIndex ) { DWORD dwRes = MIB_S_SUCCESS; DWORD dwNumEntries = 1; PMIB_IPMCAST_BOUNDARY pEntry; sav_ipMRouteBoundaryEntry *pOutput; PMIB_OPAQUE_INFO pRpcInfo = NULL; DWORD dwOutBufferSize = 0; MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index // fields, so we don't have to malloc MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0]; DWORD dwQuerySize; DWORD dwIfIndex; DWORD dwAddr; DWORD dwMask; TraceEnter("set_ipMRouteBoundaryEntry"); pOutput = (sav_ipMRouteBoundaryEntry*)objectArray; dwIfIndex = GetAsnInteger( &( pOutput->ipMRouteBoundaryIfIndex ), 0 ); dwAddr = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddress, 0 ); dwMask = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddressMask, 0 ); switch(actionId) { case MIB_ACTION_VALIDATE: // // Verify that the specified ifIndex, address, and mask are valid. // if ((dwAddr & dwMask) != dwAddr) { TRACE0( "set_ipMRouteBoundaryEntry: address/mask mismatch" ); dwRes = MIB_S_INVALID_PARAMETER; } else if (!IN_MULTICAST(ntohl(dwAddr))) { TRACE0( "set_ipMRouteBoundaryEntry: non-multicast address" ); dwRes = MIB_S_INVALID_PARAMETER; } break; case MIB_ACTION_SET: { DWORD dwInfoSize; MIB_OPAQUE_INFO pInfoBuff[2]; // big enough to hold 1 + extra index // fields, so we don't have to malloc MIB_OPAQUE_INFO *pInfo = &pInfoBuff[0]; PMIB_IPMCAST_BOUNDARY pBound = (MIB_IPMCAST_BOUNDARY *)(pInfo->rgbyData); pInfo->dwId = MCAST_BOUNDARY; pBound->dwIfIndex = dwIfIndex; pBound->dwGroupAddress = dwAddr; pBound->dwGroupMask = dwMask; pBound->dwStatus = GetAsnInteger( &pOutput->ipMRouteBoundaryStatus, 0 ); dwInfoSize = sizeof(MIB_OPAQUE_INFO) + 3*sizeof(DWORD); dwRes = SetMibInfo(actionId, pInfo, dwInfoSize); break; } case MIB_ACTION_CLEANUP: dwRes = MIB_S_SUCCESS; break; default: dwRes = MIB_S_INVALID_PARAMETER; TRACE0(" set_ipMRouteBoundaryEntry - Wrong Action "); break; } TraceLeave("set_ipMRouteBoundaryEntry"); return dwRes; } UINT get_ipMRouteScopeEntry( UINT actionId, AsnAny * objectArray, UINT * errorIndex ) { DWORD dwErr = ERROR_NOT_FOUND; DWORD dwNumEntries = 1; PMIB_IPMCAST_SCOPE pEntry; buf_ipMRouteScopeEntry *pOutput; PMIB_OPAQUE_INFO pRpcInfo = NULL; DWORD dwOutBufferSize = 0; MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index // fields, so we don't have to malloc MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0]; DWORD dwQuerySize; BYTE pScopeName[MAX_SCOPE_NAME_LEN+1]; TraceEnter("get_ipMRouteScopeEntry"); pOutput = (buf_ipMRouteScopeEntry*)objectArray; pQuery->dwVarId = MCAST_SCOPE; pQuery->rgdwVarIndex[0] = GetAsnIPAddress( &pOutput->ipMRouteScopeAddress, 0 ); pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &pOutput->ipMRouteScopeAddressMask, 0 ); dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + sizeof(DWORD); dwErr = GetMibInfo(actionId, pQuery, dwQuerySize, &pRpcInfo, &dwOutBufferSize); if (dwErr != NO_ERROR) { TraceError(dwErr); TraceLeave("get_ipMRouteScopeEntry"); if (dwErr == ERROR_NOT_FOUND) return MIB_S_ENTRY_NOT_FOUND; return dwErr; } pEntry = (PMIB_IPMCAST_SCOPE) pRpcInfo->rgbyData; // Set index values ForceSetAsnIPAddress(&(pOutput->ipMRouteScopeAddress), &(pOutput->dwIpMRouteScopeAddressInfo), pEntry->dwGroupAddress); ForceSetAsnIPAddress(&(pOutput->ipMRouteScopeAddressMask), &(pOutput->dwIpMRouteScopeAddressMaskInfo), pEntry->dwGroupMask); // Set other values. WideCharToMultiByte( CP_UTF8, 0, pEntry->snNameBuffer, wcslen(pEntry->snNameBuffer)+1, pScopeName, MAX_SCOPE_NAME_LEN+1, NULL, NULL ); SetAsnOctetString(&( pOutput->ipMRouteScopeName), pOutput->rgbyScopeNameInfo, pScopeName, min(strlen(pScopeName),MAX_SCOPE_NAME_LEN)); SetAsnInteger(&(pOutput->ipMRouteScopeStatus), ROWSTATUS_ACTIVE); if (pRpcInfo) MprAdminMIBBufferFree(pRpcInfo); TraceLeave("get_ipMRouteScopeEntry"); return MIB_S_SUCCESS; } UINT get_ipMRouteBoundaryEntry( UINT actionId, AsnAny * objectArray, UINT * errorIndex ) { DWORD dwErr = ERROR_NOT_FOUND; DWORD dwNumEntries = 1; PMIB_IPMCAST_BOUNDARY pEntry; buf_ipMRouteBoundaryEntry *pOutput; PMIB_OPAQUE_INFO pRpcInfo = NULL; DWORD dwOutBufferSize = 0; MIB_OPAQUE_QUERY pQueryBuff[2]; // big enough to hold 1 + extra index // fields, so we don't have to malloc MIB_OPAQUE_QUERY *pQuery = &pQueryBuff[0]; DWORD dwQuerySize; TraceEnter("get_ipMRouteBoundaryEntry"); pOutput = (buf_ipMRouteBoundaryEntry*)objectArray; pQuery->dwVarId = MCAST_BOUNDARY; pQuery->rgdwVarIndex[0] = GetAsnInteger( &( pOutput->ipMRouteBoundaryIfIndex ), 0 ); pQuery->rgdwVarIndex[1] = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddress, 0 ); pQuery->rgdwVarIndex[2] = GetAsnIPAddress( &pOutput->ipMRouteBoundaryAddressMask, 0 ); dwQuerySize = sizeof(MIB_OPAQUE_QUERY) + 2*sizeof(DWORD); dwErr = GetMibInfo(actionId, pQuery, dwQuerySize, &pRpcInfo, &dwOutBufferSize); if (dwErr != NO_ERROR) { TraceError(dwErr); TraceLeave("get_ipMRouteBoundaryEntry"); if (dwErr == ERROR_NOT_FOUND) return MIB_S_ENTRY_NOT_FOUND; return dwErr; } pEntry = (PMIB_IPMCAST_BOUNDARY) pRpcInfo->rgbyData; // Set index values ForceSetAsnInteger(&(pOutput->ipMRouteBoundaryIfIndex), pEntry->dwIfIndex); ForceSetAsnIPAddress(&(pOutput->ipMRouteBoundaryAddress), &(pOutput->dwIpMRouteBoundaryAddressInfo), pEntry->dwGroupAddress); ForceSetAsnIPAddress(&(pOutput->ipMRouteBoundaryAddressMask), &(pOutput->dwIpMRouteBoundaryAddressMaskInfo), pEntry->dwGroupMask); // Set other values SetAsnInteger(&(pOutput->ipMRouteBoundaryStatus), ROWSTATUS_ACTIVE); if (pRpcInfo) MprAdminMIBBufferFree(pRpcInfo); TraceLeave("get_ipMRouteBoundaryEntry"); return MIB_S_SUCCESS; } DWORD ConnectToRouter() { DWORD dwRes = (DWORD) -1; TraceEnter("ConnectToRouter"); 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 ); TraceLeave("ConnectToRouter"); return dwRes; }