/*++ Copyright (c) 1998 Microsoft Corporation Module Name: routing\monitor2\ip\mprip.c Abstract: Functions to modify transport header (global and interface) This file now contains all the function exported by ipmon.dll to the helpers Revision History: Anand Mahalingam 7/29/98 Created AmritanR --*/ #include "precomp.h" #include #pragma hdrstop #define MaxIfDisplayLength 1024 #define SetErrorType(pdw) *(pdw) = IsRouterRunning()?ERROR_ADMIN:ERROR_CONFIG BOOL g_bRouterRunning; ULONG g_ulNumChecks; VOID FreeInfoBuffer( IN PVOID pvBuffer ) { HeapFree(GetProcessHeap(), 0, pvBuffer); } DWORD WINAPI IpmontrSetInfoBlockInGlobalInfo( IN DWORD dwType, IN PBYTE pbInfoBlk, IN DWORD dwSize, IN DWORD dwCount ) /*++ Routine Description: Called to Set or Add an info block to the Global Info Arguments: pbInfoBlk - Info block to be added dwType - Type of the info block dwSize - Size of each item in the info block dwCount - Number of items in the info block Return Value: NO_ERROR --*/ { PRTR_INFO_BLOCK_HEADER pOldInfo, pNewInfo; DWORD dwErr; // // Get/update global info // dwErr = ValidateGlobalInfo(&pOldInfo); if(dwErr isnot NO_ERROR) { return dwErr; } if(MprInfoBlockExists(pOldInfo, dwType)) { // // The block already exists. So call set to replace it // dwErr = MprInfoBlockSet(pOldInfo, dwType, dwSize, dwCount, pbInfoBlk, &pNewInfo); } else { // // No info currently, add it // dwErr = MprInfoBlockAdd(pOldInfo, dwType, dwSize, dwCount, pbInfoBlk, &pNewInfo); } // // Dont need the old info // FREE_BUFFER(pOldInfo); if(dwErr isnot NO_ERROR) { if(!g_bCommit) { g_tiTransport.pibhInfo = NULL; g_tiTransport.bValid = FALSE; } return dwErr; } // // If in commit mode, set it to the router/registry // Otherwise update the local copy // if(g_bCommit) { dwErr = SetGlobalInfo(pNewInfo); FREE_BUFFER(pNewInfo); } else { ASSERT(g_tiTransport.bValid); g_tiTransport.pibhInfo = pNewInfo; dwErr = NO_ERROR; } return dwErr; } DWORD WINAPI IpmontrSetInfoBlockInInterfaceInfo( IN LPCWSTR pwszIfName, IN DWORD dwType, IN PBYTE pbInfoBlk, IN DWORD dwSize, IN DWORD dwCount ) /*++ Routine Description: Adds or Sets and infoblock in the interface info Arguments: pwszIfName - interface name pbInfoBlk - Info block to be added dwType - Type of the info block dwSize - Size of each item in the info block dwCount - Number of items in the info block Return Value: NO_ERROR --*/ { PRTR_INFO_BLOCK_HEADER pOldInfo, pNewInfo; DWORD dwErr; PINTERFACE_STORE pii; pii = NULL; // // Get/Update the interface info // dwErr = ValidateInterfaceInfo(pwszIfName, &pOldInfo, NULL, &pii); if(dwErr isnot NO_ERROR) { return dwErr; } if(MprInfoBlockExists(pOldInfo, dwType)) { // // The block already exists call Set to replace // dwErr = MprInfoBlockSet(pOldInfo, dwType, dwSize, dwCount, pbInfoBlk, &pNewInfo); } else { dwErr = MprInfoBlockAdd(pOldInfo, dwType, dwSize, dwCount, pbInfoBlk, &pNewInfo); } FREE_BUFFER(pOldInfo); if(dwErr isnot NO_ERROR) { // // Some error - invalidate info // if(!g_bCommit) { ASSERT(pii); ASSERT(pii->bValid); pii->pibhInfo = NULL; pii->bValid = FALSE; } return dwErr; } if(g_bCommit) { // // Set to router/registry // dwErr = SetInterfaceInfo(pNewInfo, pwszIfName); FREE_BUFFER(pNewInfo); } else { // // Update local copy with new info (old one has been freed) // ASSERT(pii); ASSERT(pii->bValid); pii->pibhInfo = pNewInfo; pii->bValid = TRUE; dwErr = NO_ERROR; } return dwErr; } DWORD WINAPI IpmontrDeleteInfoBlockFromGlobalInfo( IN DWORD dwType ) /*++ Routine Description: Deletes an infoblock from the global info. The Infoblock is deleted by setting its Size and Count to 0 Arguments: dwType - Id of Protocol to be added Return Value: NO_ERROR --*/ { DWORD dwErr = NO_ERROR; PRTR_INFO_BLOCK_HEADER pOldInfo, pNewInfo; dwErr = ValidateGlobalInfo(&pOldInfo); if(dwErr isnot NO_ERROR) { return dwErr; } if(!MprInfoBlockExists(pOldInfo, dwType)) { if(g_bCommit) { // // Arent saving a local copy so free this info // FREE_BUFFER(pOldInfo); } return NO_ERROR; } // // The router manager will only delete config info if we set // the size to 0. However, we don't want to write 0-size // blocks to the registry, so we will strip them out when // we write to the registry. // dwErr = MprInfoBlockSet(pOldInfo, dwType, 0, 0, NULL, &pNewInfo); FREE_BUFFER(pOldInfo); if(dwErr isnot NO_ERROR) { if(!g_bCommit) { ASSERT(g_tiTransport.bValid); g_tiTransport.pibhInfo = NULL; g_tiTransport.bValid = FALSE; } return dwErr; } if(g_bCommit) { dwErr = SetGlobalInfo(pNewInfo); FREE_BUFFER(pNewInfo); } else { ASSERT(g_tiTransport.bValid); g_tiTransport.pibhInfo = pNewInfo; dwErr = NO_ERROR; } return dwErr; } DWORD WINAPI IpmontrDeleteInfoBlockFromInterfaceInfo( IN LPCWSTR pwszIfName, IN DWORD dwType ) /*++ Routine Description: Deletes an info block from the interface info. The info block is deleted by setting its Size and Count to 0 Arguments: pwszIfName - Interface on which to add the protocol dwType - Id of Protocol to be added Return Value: NO_ERROR --*/ { DWORD dwErr; PRTR_INFO_BLOCK_HEADER pOldInfo, pNewInfo; PINTERFACE_STORE pii; pii = NULL; dwErr = ValidateInterfaceInfo(pwszIfName, &pOldInfo, NULL, &pii); if (dwErr isnot NO_ERROR) { return dwErr; } if(!MprInfoBlockExists(pOldInfo, dwType)) { if (g_bCommit) { FREE_BUFFER(pOldInfo); } return NO_ERROR; } // // If it does exist, remove it // This creates a new block // HACKHACK - Again we can interchangeably use info that is allocated // by GetXxx functions and MprInfoBlock functions since both allocations // are from ProcessHeap() // // // The router manager will only delete config info if we set // the size to 0. However, we don't want to write 0-size // blocks to the registry, so we will strip them out when // we write to the registry. // dwErr = MprInfoBlockSet(pOldInfo, dwType, 0, 0, NULL, &pNewInfo); // // One way or another, done with the old info // FREE_BUFFER(pOldInfo); if(dwErr isnot NO_ERROR) { if(!g_bCommit) { ASSERT(pii); ASSERT(pii->bValid); pii->pibhInfo = NULL; pii->bValid = FALSE; } return dwErr; } if(g_bCommit) { dwErr = SetInterfaceInfo(pNewInfo, pwszIfName); FREE_BUFFER(pNewInfo); } else { ASSERT(pii); ASSERT(pii->bValid); pii->pibhInfo = pNewInfo; pii->bValid = TRUE; dwErr = NO_ERROR; } return dwErr; } DWORD WINAPI IpmontrDeleteProtocol( IN DWORD dwProtoId ) /*++ Routine Description: Deletes Protocol from a transport Arguments: dwProtoId - Id of Protocol to be deleted Return Value: NO_ERROR --*/ { DWORD dwRes; PMPR_INTERFACE_0 pmi0; DWORD dwCnt, dwTot, dwInd, dwCount, dwErrType; SetErrorType(&dwErrType); do { // // Protocol being deleted globally, so remove from // all interfaces. // dwRes = IpmontrInterfaceEnum((PBYTE *) &pmi0, &dwCnt, &dwTot); if(dwRes != NO_ERROR) { DisplayMessage(g_hModule, dwErrType, dwRes); break; } if (pmi0 == NULL) { dwCnt = 0; } for (dwInd = 0; dwInd < dwCnt; dwInd++) { dwRes = IpmontrDeleteInfoBlockFromInterfaceInfo(pmi0[dwInd].wszInterfaceName, dwProtoId); if (dwRes is ERROR_NOT_ENOUGH_MEMORY) { break; } } // // Remove protocol from global info // dwRes = IpmontrDeleteInfoBlockFromGlobalInfo(dwProtoId); if (dwRes != NO_ERROR) { break; } } while(FALSE); if (pmi0) { HeapFree(GetProcessHeap(), 0, pmi0); } return dwRes; } DWORD WINAPI IpmontrGetInfoBlockFromGlobalInfo( IN DWORD dwType, OUT BYTE **ppbInfoBlk, OPTIONAL OUT PDWORD pdwSize, OPTIONAL OUT PDWORD pdwCount OPTIONAL ) /*++ Routine Description: Gets the info block from global info. If we get a zero sized block we return ERROR_NOT_FOUND so as to not configure the caller Arguments: dwType - Type of the info block ppbInfoBlk - ptr to info block pdwSize - size of each item in block pdwCount - number of items in block Return Value: NO_ERROR ERROR_NOT_FOUND if the block doesnt exist. --*/ { PRTR_INFO_BLOCK_HEADER pInfo; DWORD dwErr; BOOL *pbValid; PBYTE pbyTmp = NULL; DWORD dwSize, dwCnt; if(ppbInfoBlk) { *ppbInfoBlk = NULL; } if(pdwSize) { *pdwSize = 0; } if(pdwCount) { *pdwCount = 0; } dwErr = ValidateGlobalInfo(&pInfo); if(dwErr isnot NO_ERROR) { return dwErr; } dwErr = MprInfoBlockFind(pInfo, dwType, &dwSize, &dwCnt, &pbyTmp); if(dwErr is NO_ERROR) { if(dwSize is 0) { if(g_bCommit) { FREE_BUFFER(pInfo); } return ERROR_NOT_FOUND; } if(ppbInfoBlk) { *ppbInfoBlk = HeapAlloc(GetProcessHeap(), 0, dwSize * dwCnt); if(*ppbInfoBlk is NULL) { if(g_bCommit) { FREE_BUFFER(pInfo); } return ERROR_NOT_ENOUGH_MEMORY; } CopyMemory(*ppbInfoBlk, pbyTmp, dwSize * dwCnt); } if(pdwSize) { *pdwSize = dwSize; } if(pdwCount) { *pdwCount = dwCnt; } } if(g_bCommit) { FREE_BUFFER(pInfo); } return dwErr; } DWORD WINAPI IpmontrGetInfoBlockFromInterfaceInfo( IN LPCWSTR pwszIfName, IN DWORD dwType, OUT BYTE **ppbInfoBlk, OPTIONAL OUT PDWORD pdwSize, OPTIONAL OUT PDWORD pdwCount, OPTIONAL OUT PDWORD pdwIfType OPTIONAL ) /*++ Routine Description: Gets the info block from interface transport header Arguments: pwszIfName - Interface Name dwType - Type of the info block ppbInfoBlk - ptr to info block pdwSize - size of each item in block pdwCount - number of items in block pdwIfType - interface type Return Value: NO_ERROR ERROR_NOT_FOUND --*/ { PRTR_INFO_BLOCK_HEADER pInfo, *ppInfo; DWORD dwErr; PBYTE pbTmp, pbyTmp; DWORD dwSize, dwCount; if(ppbInfoBlk) { *ppbInfoBlk = NULL; } if(pdwSize) { *pdwSize = 0; } if(pdwCount) { *pdwCount = 0; } // // If the user doesnt want any info, size or count, then we can optimize // a bit by passing NULL to validate // if(((ULONG_PTR)ppbInfoBlk | (ULONG_PTR)pdwSize | (ULONG_PTR)pdwCount)) { ppInfo = &pInfo; } else { ppInfo = NULL; } dwErr = ValidateInterfaceInfo(pwszIfName, ppInfo, pdwIfType, NULL); if((dwErr isnot NO_ERROR) or (ppInfo is NULL)) { // // If the user had an error or only wanted the ifType we are done // return dwErr; } // // Return protocol block info. // dwErr = MprInfoBlockFind(pInfo, dwType, &dwSize, &dwCount, &pbyTmp); if(dwErr is NO_ERROR) { if(dwSize is 0) { if(g_bCommit) { FREE_BUFFER(pInfo); } return ERROR_NOT_FOUND; } if(ppbInfoBlk) { *ppbInfoBlk = HeapAlloc(GetProcessHeap(), 0, dwSize * dwCount); if(*ppbInfoBlk is NULL) { if(g_bCommit) { FREE_BUFFER(pInfo); } return ERROR_NOT_ENOUGH_MEMORY; } CopyMemory(*ppbInfoBlk, pbyTmp, dwSize * dwCount); if(pdwSize) { *pdwSize = dwSize; } if(pdwCount) { *pdwCount = dwCount; } } } if(g_bCommit) { FREE_BUFFER(pInfo); } return dwErr; } DWORD WINAPI IpmontrGetInterfaceType( IN LPCWSTR pwszIfName, OUT PDWORD pdwIfType ) { return GetInterfaceInfo(pwszIfName, NULL, NULL, pdwIfType); } DWORD WINAPI GetInterfaceName( IN LPCWSTR ptcArgument, OUT LPWSTR pwszIfName, IN DWORD dwSizeOfIfName, OUT PDWORD pdwNumParsed ) /*++ Description: Convert a friendly name to an interface name Arguments: ptcArgument - Buffer holding the Friendly Name of an interface pwszIfName - Buffer to hold the Guid Interface Name dwSizeOfIfName - Size (in Bytes) of the pwszIfName pdwNumParsed - --*/ { DWORD dwErr; dwErr = IpmontrGetIfNameFromFriendlyName( ptcArgument, pwszIfName, &dwSizeOfIfName ); *pdwNumParsed = (dwErr is NO_ERROR)? 1 : 0; return dwErr; } DWORD WINAPI GetInterfaceDescription( IN LPCWSTR pwszIfName, OUT LPWSTR pwszIfDesc, OUT PDWORD pdwNumParsed ) { DWORD rc,dwSize; WCHAR IfNamBuffer[MaxIfDisplayLength]; DWORD dwLen = (DWORD) wcslen(pwszIfName); if ( !dwLen || dwLen > MAX_INTERFACE_NAME_LEN ) { *pdwNumParsed = 0; return ERROR_INVALID_PARAMETER; } dwSize = sizeof(IfNamBuffer); //====================================== // Translate the Interface Name //====================================== rc = IpmontrGetFriendlyNameFromIfName(pwszIfName, IfNamBuffer, &dwSize); if (rc == NO_ERROR) { wcscpy(pwszIfDesc,IfNamBuffer); *pdwNumParsed = 1; } else { *pdwNumParsed = 0; } return rc; } DWORD WINAPI IpmontrInterfaceEnum( OUT PBYTE *ppb, OUT PDWORD pdwCount, OUT PDWORD pdwTotal ) { DWORD dwRes; PMPR_INTERFACE_0 pmi0; if(!IsRouterRunning()) { dwRes = MprConfigInterfaceEnum(g_hMprConfig, 0, (LPBYTE*) &pmi0, (DWORD) -1, pdwCount, pdwTotal, NULL); if(dwRes == NO_ERROR) { *ppb = (PBYTE)pmi0; } } else { dwRes = MprAdminInterfaceEnum(g_hMprAdmin, 0, (LPBYTE*) &pmi0, (DWORD) -1, pdwCount, pdwTotal, NULL); if(dwRes == NO_ERROR) { *ppb = HeapAlloc(GetProcessHeap(), 0, sizeof(MPR_INTERFACE_0) * (*pdwCount)); if(*ppb == NULL) { DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY); return ERROR_NOT_ENOUGH_MEMORY; } CopyMemory(*ppb, pmi0, sizeof(MPR_INTERFACE_0) * (*pdwCount)); MprAdminBufferFree(pmi0); } } return dwRes; } DWORD WINAPI MatchRoutingProtoTag( IN LPCWSTR pwszToken ) /*++ Routine Description: Gets the protocol ID corresponding to a protocol tag. Arguments: pwszArg - protocol token Return Value: Protocol Id or (DWORD)-1 --*/ { DWORD dwRes, dwErr; TOKEN_VALUE rgEnums[] ={{TOKEN_VALUE_RIP, PROTO_IP_RIP}, {TOKEN_VALUE_OSPF, PROTO_IP_OSPF}, {TOKEN_VALUE_AUTOSTATIC, PROTO_IP_NT_AUTOSTATIC}, {TOKEN_VALUE_STATIC, PROTO_IP_NT_STATIC}, {TOKEN_VALUE_NETMGMT, PROTO_IP_NETMGMT}, {TOKEN_VALUE_LOCAL, PROTO_IP_LOCAL}, {TOKEN_VALUE_NONDOD, PROTO_IP_NT_STATIC_NON_DOD}}; if (iswdigit(pwszToken[0])) { return wcstoul(pwszToken, NULL, 10); } dwErr = MatchEnumTag(g_hModule, pwszToken, sizeof(rgEnums)/sizeof(TOKEN_VALUE), rgEnums, &dwRes); if(dwErr != NO_ERROR) { return (DWORD)-1; } return dwRes; } BOOL WINAPI IsRouterRunning( VOID ) /*++ Routine Description: Gets the protocol ID corresponding to a protocol tag. Arguments: pwszArg - protocol token Return Value: Protocol Id or (DWORD)-1 --*/ { DWORD dwErr; // // Check at most once per second // // We don't care about wrapping, we just need a fast way to // get some identifier of the current "second". // static time_t dwPreviousTime = 0; time_t dwCurrentTime; time(&dwCurrentTime); if (dwCurrentTime == dwPreviousTime) { return g_bRouterRunning; } dwPreviousTime = dwCurrentTime; if(MprAdminIsServiceRunning(g_pwszRouter)) { if(g_bRouterRunning) { return TRUE; } dwErr = MprAdminServerConnect(g_pwszRouter, &g_hMprAdmin); if(dwErr isnot NO_ERROR) { DisplayError(NULL, dwErr); DisplayMessage(g_hModule, MSG_IP_CAN_NOT_CONNECT_DIM, dwErr); return FALSE; } dwErr = MprAdminMIBServerConnect(g_pwszRouter, &g_hMIBServer); if(dwErr isnot NO_ERROR) { DisplayError(NULL, dwErr); DisplayMessage(g_hModule, MSG_IP_CAN_NOT_CONNECT_DIM, dwErr); MprAdminServerDisconnect(g_hMprAdmin); g_hMprAdmin = NULL; return FALSE; } g_bRouterRunning = TRUE; } else { if(g_bRouterRunning) { g_bRouterRunning = FALSE; g_hMprAdmin = NULL; g_hMIBServer = NULL; } } return g_bRouterRunning; } DWORD MibGetFirst( DWORD dwTransportId, DWORD dwRoutingPid, LPVOID lpInEntry, DWORD dwInEntrySize, LPVOID *lplpOutEntry, LPDWORD lpdwOutEntrySize ) { DWORD dwErr; dwErr = MprAdminMIBEntryGetFirst( g_hMIBServer, dwTransportId, dwRoutingPid, lpInEntry, dwInEntrySize, lplpOutEntry, lpdwOutEntrySize ); if (dwErr is RPC_S_INVALID_BINDING) { g_bRouterRunning = FALSE; g_hMprAdmin = NULL; g_hMIBServer = NULL; } return dwErr; } DWORD MibGetNext( DWORD dwTransportId, DWORD dwRoutingPid, LPVOID lpInEntry, DWORD dwInEntrySize, LPVOID *lplpOutEntry, LPDWORD lpdwOutEntrySize ) { DWORD dwErr; dwErr = MprAdminMIBEntryGetNext( g_hMIBServer, dwTransportId, dwRoutingPid, lpInEntry, dwInEntrySize, lplpOutEntry, lpdwOutEntrySize ); if (dwErr is RPC_S_INVALID_BINDING) { g_bRouterRunning = FALSE; g_hMprAdmin = NULL; g_hMIBServer = NULL; } return dwErr; } DWORD MibGet( DWORD dwTransportId, DWORD dwRoutingPid, LPVOID lpInEntry, DWORD dwInEntrySize, LPVOID *lplpOutEntry, LPDWORD lpdwOutEntrySize ) { DWORD dwErr; dwErr = MprAdminMIBEntryGet( g_hMIBServer, dwTransportId, dwRoutingPid, lpInEntry, dwInEntrySize, lplpOutEntry, lpdwOutEntrySize ); if (dwErr is RPC_S_INVALID_BINDING) { g_bRouterRunning = FALSE; g_hMprAdmin = NULL; g_hMIBServer = NULL; } return dwErr; }