#include "precomp.h" #pragma hdrstop #ifdef SN_UNICODE # define sn_strlen wcslen # define sn_strcpy wcscpy # define sn_sprintf wsprintf # define sn_strcmp wcscmp # define SN_EMPTYSTRING L"" # define SN_L L #else # define sn_strlen strlen # define sn_strcpy strcpy # define sn_sprintf sprintf # define sn_strcmp strcmp # define SN_EMPTYSTRING "" # define SN_L #endif IPV4_ADDRESS g_ipGrpAddr, g_ipGrpMask; SCOPE_NAME g_snScopeName; enum RouterOps { ADD_BOUNDARY = 1, DELETE_BOUNDARY, ADD_SCOPE, DELETE_SCOPE, SET_SCOPE }; typedef struct _SCOPE_ENTRY { IPV4_ADDRESS ipGroupAddress; IPV4_ADDRESS ipGroupMask; ULONG ulNumNames; BOOL bDivisible; LANGID idLanguage; SCOPE_NAME_BUFFER snScopeNameBuffer; DWORD dwNumInterfaces; } SCOPE_ENTRY, *PSCOPE_ENTRY; #define MIN_SCOPE_ADDR 0xef000000 #define MAX_SCOPE_ADDR (0xefff0000 - 1) DWORD UpdateBoundaryBlock( IN DWORD dwAction, IN PBYTE pib, OUT PBYTE *ppibNew, IN OUT DWORD *pdwBlkSize, IN OUT DWORD *pdwCount, OUT BOOL *bChanged ); PSCOPE_ENTRY FindScopeByPrefix( IN IPV4_ADDRESS ipGroupAddress, IN IPV4_ADDRESS ipGroupMask, IN PSCOPE_ENTRY pScopes, IN ULONG ulNumScopes ) { DWORD dwInd; for (dwInd = 0; dwInd < ulNumScopes; dwInd++) { if ( pScopes[dwInd].ipGroupAddress == ipGroupAddress && pScopes[dwInd].ipGroupMask == ipGroupMask ) { return &pScopes[dwInd]; } } return NULL; } DWORD FindScopeByName( IN SCOPE_NAME snScopeName, IN PSCOPE_ENTRY pScopes, IN ULONG ulNumScopes, OUT PSCOPE_ENTRY *ppScope ) { DWORD dwErr = NO_ERROR; ULONG i, j, dwCnt = 0; for (i = 0; i < ulNumScopes; i++) { if ( !sn_strcmp(snScopeName, pScopes[i].snScopeNameBuffer)) { *ppScope = &pScopes[i]; dwCnt++; } } switch (dwCnt) { case 0: *ppScope = NULL; return ERROR_NOT_FOUND; case 1: return NO_ERROR; default: return ERROR_MORE_DATA; } } DWORD MakeInfoFromScopes2( OUT PBYTE pBuffer, IN OUT ULONG *pulBufferLen, IN PSCOPE_ENTRY pScopes, IN ULONG ulNumScopes ) /*++ Description: Compose registry block from array of scopes. --*/ { DWORD dwLen, i, dwSize, dwNumNames, j, dwLanguage, dwFlags; PLIST_ENTRY pleNode; if (ulNumScopes is 0) { *pulBufferLen = 0; return NO_ERROR; } // Compute size needed dwSize = sizeof(DWORD); for (i=0; i< ulNumScopes; i++) { dwSize += 2 * sizeof(IPV4_ADDRESS) + 2 * sizeof(DWORD); // Currently we only store at most one name. for (j=0; j *pulBufferLen) { *pulBufferLen = dwSize; return ERROR_INSUFFICIENT_BUFFER; } // // Save scope count in first DWORD // *((PDWORD) pBuffer) = ulNumScopes; pBuffer += sizeof(DWORD); // // Now step through and add each scope to the buffer // for (i=0; i< ulNumScopes; i++) { // Copy scope address, and mask dwLen = 2 * sizeof(IPV4_ADDRESS); CopyMemory(pBuffer, &pScopes[i], dwLen); pBuffer += dwLen; // Copy flags dwFlags = pScopes[i].bDivisible; CopyMemory(pBuffer, &dwFlags, sizeof(dwFlags)); pBuffer += sizeof(dwFlags); // Copy # of names CopyMemory(pBuffer, &pScopes[i].ulNumNames, sizeof(DWORD)); pBuffer += sizeof(DWORD); // Currently we only save at most one name for (j=0; jipGroupAddress; *pipScopeMask = pScope->ipGroupMask; dwErr = NO_ERROR; } FREE(pScopes); } if (pBuffer) FREE(pBuffer); return dwErr; } DWORD UpdateScope( IN PSCOPE_ENTRY pScopeToUpdate, IN PSCOPE_ENTRY pScopes, IN ULONG ulNumScopes, OUT PBYTE *ppibNew, OUT DWORD *pdwSizeNew ) /*++ Description: Caller is responsible for freeing buffer returned. --*/ { // Update the scope name sn_strcpy(pScopeToUpdate->snScopeNameBuffer, g_snScopeName); pScopeToUpdate->ulNumNames = 1; pScopeToUpdate->idLanguage = GetUserDefaultLangID(); // Now convert the array to a buffer return MakeInfoFromScopes( ppibNew, pdwSizeNew, pScopes, ulNumScopes); } DWORD DeleteBoundaryFromInterface( IN LPCWSTR pwszIfName, IN PSCOPE_ENTRY pScopeToDelete ) { BOOL bChanged; DWORD dwErr, dwBlkSize, dwCount, dwIfType; PBYTE pibNew, pib; dwErr = IpmontrGetInfoBlockFromInterfaceInfo( pwszIfName, IP_MCAST_BOUNDARY_INFO, &pib, &dwBlkSize, &dwCount, &dwIfType ); if (dwErr is ERROR_NOT_FOUND) return NO_ERROR; if (dwErr isnot NO_ERROR) return dwErr; dwErr = UpdateBoundaryBlock( DELETE_BOUNDARY, pib, &pibNew, &dwBlkSize, &dwCount, &bChanged ); if (dwErr is NO_ERROR && bChanged) { dwErr = IpmontrSetInfoBlockInInterfaceInfo( pwszIfName, IP_MCAST_BOUNDARY_INFO, pibNew, dwBlkSize, dwCount ); } if (pib) FREE(pib); if (pibNew) FREE(pibNew); return dwErr; } DWORD DeleteScopeBoundaries( IN PSCOPE_ENTRY pScopeToDelete ) { DWORD dwErr, dwCount, dwTotal, i; PMPR_INTERFACE_0 pmi0; // Enumerate interfaces dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0, &dwCount, &dwTotal); if (dwErr isnot NO_ERROR) { DisplayError(g_hModule, dwErr); return dwErr; } // Delete scope boundaries for each interface for ( i = 0; i < dwCount && dwErr is NO_ERROR; i++) { dwErr = DeleteBoundaryFromInterface( pmi0[i].wszInterfaceName, pScopeToDelete ); // Ignore ERROR_NO_SUCH_INTERFACE since it may be that IP // is not enabled on the interface, so we expect to get this // error sometimes. if (dwErr is ERROR_NO_SUCH_INTERFACE) { dwErr = NO_ERROR; } } return dwErr; } DWORD DeleteScope( IN PSCOPE_ENTRY pScopeToDelete, IN PSCOPE_ENTRY pScopes, IN ULONG *pulNumScopes, OUT PBYTE *ppibNew, OUT DWORD *pdwSizeNew ) /*++ Description: Creates a new info block which does not include the scope given by pScopeToDelete. Caller is responsible for freeing buffer returned. Called by: UpdateScopeBlock() --*/ { DWORD dwErr; // Delete all boundaries for this scope dwErr = DeleteScopeBoundaries(pScopeToDelete); if (dwErr isnot NO_ERROR) return dwErr; // Delete the scope from the array MoveMemory( pScopeToDelete, pScopeToDelete+1, ((PBYTE)(pScopes + *pulNumScopes)) - ((PBYTE)(pScopeToDelete + 1) )); (*pulNumScopes)--; // Now convert the array to a buffer return MakeInfoFromScopes( ppibNew, pdwSizeNew, pScopes, *pulNumScopes); } DWORD AddScope( IN OUT PSCOPE_ENTRY *ppScopes, IN ULONG *pulNumScopes, OUT PBYTE *ppibNew, OUT DWORD *pdwSizeNew ) /*++ Description: Creates a new info block which includes the scope given by g_snScopeName, g_dwDstAddr, and g_dwDstMask. Caller is responsible for freeing buffer returned. Called by: UpdateScopeBlock() --*/ { PBYTE *pBuff; DWORD dwRes = NO_ERROR, dwInd, dwSize = 0, dwSizeReqd = 0; SCOPE_ENTRY *pScopes = *ppScopes; do { // Make room for the new scope if (*pulNumScopes > 0) pScopes = REALLOC( pScopes, (*pulNumScopes + 1) * sizeof(SCOPE_ENTRY) ); else pScopes = MALLOC( sizeof(SCOPE_ENTRY) ); if (!pScopes) return ERROR_NOT_ENOUGH_MEMORY; dwInd = (*pulNumScopes)++; // Fill in the new scope ZeroMemory(&pScopes[dwInd], sizeof(SCOPE_ENTRY)); pScopes[dwInd].ipGroupAddress = g_ipGrpAddr; pScopes[dwInd].ipGroupMask = g_ipGrpMask; sn_strcpy(pScopes[dwInd].snScopeNameBuffer, g_snScopeName); pScopes[dwInd].ulNumNames = 1; pScopes[dwInd].idLanguage = GetUserDefaultLangID(); // Now convert the array to a buffer dwRes = MakeInfoFromScopes( ppibNew, &dwSize, pScopes, *pulNumScopes); } while ( FALSE ); *pdwSizeNew = dwSize; *ppScopes = pScopes; return dwRes; } BOOL IsContiguous( IN IPV4_ADDRESS dwMask ) { register int i; dwMask = ntohl(dwMask); // Set i to index of lowest 1 bit, or 32 if none for (i=0; i<32 && !(dwMask & (1< MAX_SCOPE_ADDR) { dwRes = ERROR_INVALID_PARAMETER; break; } // Make sure mask is contiguous if (!IsContiguous(g_ipGrpMask)) { char buff[20], *lpstr; lpstr = inet_ntoa( *((struct in_addr *) &g_ipGrpMask)); if (lpstr != NULL) { strcpy( buff, lpstr ); DisplayMessage( g_hModule, MSG_IP_BAD_IP_MASK, buff ); } break; } // // Find if specified scope is present // pScopes = GetScopesFromInfo( pib, &ulNumScopes ); if ( pScopes ) { pFoundScope = FindScopeByPrefix( g_ipGrpAddr, g_ipGrpMask, pScopes, ulNumScopes ); } // // Update the scope infoblock. // switch ( dwAction ) { case ADD_SCOPE: // // If scope is not present, add it. Else return error. // if ( !pFoundScope ) { dwRes = AddScope( &pScopes, &ulNumScopes, ppibNew, &dwSize ); if ( dwRes == NO_ERROR ) { *pdwBlkSize = dwSize; *pdwCount = 1; } break; } // else fall through into SET_SCOPE. case SET_SCOPE: // // if scope present, update it. // if ( pFoundScope ) { dwRes = UpdateScope( pFoundScope, pScopes, ulNumScopes, ppibNew, &dwSize ); if ( dwRes == NO_ERROR ) { *pdwBlkSize = dwSize; *pdwCount = 1; } } else { dwRes = ERROR_INVALID_PARAMETER; } break; case DELETE_SCOPE: // // Delete scope only if present. // if ( pFoundScope ) { dwRes = DeleteScope( pFoundScope, pScopes, &ulNumScopes, ppibNew, &dwSize ); if ( dwRes == NO_ERROR ) { *pdwBlkSize = dwSize; *pdwCount = (dwSize>0)? 1 : 0; } } else { dwRes = ERROR_INVALID_PARAMETER; } break; } } while ( FALSE ); if (pScopes) FREE( pScopes ); return dwRes; } DWORD VerifyBoundaryPrefix( IPV4_ADDRESS ipAddr, IPV4_ADDRESS ipMask ) { WCHAR wstr1[20], wstr2[20]; // // Verify boundary info. // if (ntohl(ipAddr) < MIN_SCOPE_ADDR || ntohl(ipAddr) > MAX_SCOPE_ADDR) { MakeAddressStringW(wstr1, htonl(MIN_SCOPE_ADDR)); MakeAddressStringW(wstr2, htonl(MAX_SCOPE_ADDR)); DisplayMessage( g_hModule, EMSG_INVALID_ADDR, wstr1, wstr2 ); return ERROR_INVALID_PARAMETER; } if ( ( ipAddr & ipMask ) != ipAddr ) { DisplayMessage( g_hModule, EMSG_PREFIX_ERROR ); return ERROR_INVALID_PARAMETER; } // Make sure mask is contiguous if (!IsContiguous(ipMask)) { char buff[20], *lpstr; lpstr = inet_ntoa( *((struct in_addr *) &g_ipGrpMask)); if (lpstr != NULL) { strcpy( buff, lpstr ); DisplayMessage( g_hModule, MSG_IP_BAD_IP_MASK, buff ); } return ERROR_INVALID_PARAMETER; } return NO_ERROR; } DWORD IpAddSetDelScope( DWORD dwAction, PWCHAR *ppwcArguments, DWORD dwCurrentIndex, DWORD dwArgCount ) { DWORD dwErr; TAG_TYPE pttTags[] = {{TOKEN_GROUP_ADDRESS,FALSE,FALSE}, {TOKEN_GROUP_MASK, FALSE,FALSE}, {TOKEN_SCOPE_NAME, FALSE,FALSE}}; SCOPE_NAME_BUFFER snScopeName; DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)]; IPV4_ADDRESS ipGroup, ipMask; DWORD dwBlkSize, dwCount, i, dwNumParsed; PBYTE pib, pibNew = NULL; DWORD dwArgsReqd = (dwAction is DELETE_SCOPE)? 1 : 3; PWCHAR p; // Do generic processing dwErr = PreHandleCommand( ppwcArguments, dwCurrentIndex, dwArgCount, pttTags, sizeof(pttTags)/sizeof(TAG_TYPE), dwArgsReqd, sizeof(pttTags)/sizeof(TAG_TYPE), rgdwTagType ); if (dwErr) { return dwErr; } g_ipGrpAddr = g_ipGrpMask = 0; for(i = 0; i < dwArgCount - dwCurrentIndex; i ++) { switch (rgdwTagType[i]) { case 1: // GRPMASK { dwErr = GetIpMask(ppwcArguments[i + dwCurrentIndex], &g_ipGrpMask); if (dwErr is ERROR_INVALID_PARAMETER) { DisplayMessage( g_hModule, MSG_IP_BAD_IP_ADDR, ppwcArguments[i + dwCurrentIndex]); DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE, pttTags[rgdwTagType[i]].pwszTag, ppwcArguments[i + dwCurrentIndex]); return NO_ERROR; } break; } case 0: // GRPADDR { dwErr = GetIpPrefix(ppwcArguments[i + dwCurrentIndex], &g_ipGrpAddr, &g_ipGrpMask); if (!((dwErr is ERROR_INVALID_PARAMETER) && (dwAction is DELETE_SCOPE))) { break; } // FALLTHROUGH } case 2 : // SCOPENAME { // Strip leading and trailing whitespace for (p = ppwcArguments[i + dwCurrentIndex]; iswspace(*p); p++); while (iswspace( p[wcslen(p) - 1] )) { p[ wcslen(p)-1 ] = 0; } if (wcslen(p) > MAX_SCOPE_NAME_LEN) { DisplayMessage( g_hModule, EMSG_SCOPE_NAME_TOO_LONG, MAX_SCOPE_NAME_LEN ); return NO_ERROR; } sn_strcpy( snScopeName, p); g_snScopeName = snScopeName; if (dwAction is DELETE_SCOPE) { dwErr = ScopeNameToPrefix(snScopeName, &g_ipGrpAddr, &g_ipGrpMask); if (dwErr is ERROR_MORE_DATA) { DisplayMessage( g_hModule, EMSG_AMBIGUOUS_SCOPE_NAME, ppwcArguments[i + dwCurrentIndex]); return NO_ERROR; } } break; } } } if (dwErr isnot NO_ERROR) { return dwErr; } if (!g_ipGrpAddr || !g_ipGrpMask) { return ERROR_INVALID_SYNTAX; } dwErr = VerifyBoundaryPrefix(g_ipGrpAddr, g_ipGrpMask); if (dwErr) { return NO_ERROR; } do { dwErr = IpmontrGetInfoBlockFromGlobalInfo( IP_MCAST_BOUNDARY_INFO, &pib, &dwBlkSize, &dwCount ); if (dwErr is ERROR_NOT_FOUND) { // // No info of this type is currently present // dwErr = NO_ERROR; dwCount = 1; } if (dwErr isnot NO_ERROR) break; dwErr = UpdateScopeBlock( dwAction, pib, &pibNew, &dwBlkSize, &dwCount ); if (dwErr isnot NO_ERROR) break; dwErr = IpmontrSetInfoBlockInGlobalInfo( IP_MCAST_BOUNDARY_INFO, pibNew, dwBlkSize, dwCount ); } while (FALSE); if (pib) HeapFree(GetProcessHeap(), 0 , pib); if (pibNew) HeapFree(GetProcessHeap(), 0 , pibNew); return dwErr; } DWORD HandleIpAddScope( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) /*++ Routine Description: Arguments: ppwcArguments - Argument array dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg Return Value: NO_ERROR --*/ { return IpAddSetDelScope( ADD_SCOPE, ppwcArguments, dwCurrentIndex, dwArgCount ); } DWORD HandleIpDelScope( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) /*++ Routine Description: Arguments: ppwcArguments - Argument array dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg Return Value: NO_ERROR --*/ { return IpAddSetDelScope( DELETE_SCOPE, ppwcArguments, dwCurrentIndex, dwArgCount ); } DWORD HandleIpSetScope( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) /*++ Routine Description: Arguments: ppwcArguments - Argument array dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg Return Value: NO_ERROR --*/ { return IpAddSetDelScope( SET_SCOPE, ppwcArguments, dwCurrentIndex, dwArgCount ); } DWORD ShowScopes( IN HANDLE hFile ) { DWORD dwRes = (DWORD) -1, dwCnt = 0, dwInd = 0, dwGlobalSize = 0; ULONG ulNumScopes = 0; CHAR szAddr1[ ADDR_LENGTH ], szAddr2[ ADDR_LENGTH ]; PSCOPE_ENTRY pScope, pScopes; HANDLE hTransport = (HANDLE) NULL; PBYTE pScopesBuffer; SCOPE_NAME_BUFFER snScopeNameBuffer; do { pScopes = GetScopes( &ulNumScopes, &pScopesBuffer ); if (hFile is NULL) { if (ulNumScopes) { DisplayMessage( g_hModule, MSG_RTR_SCOPE_HDR ); } else { DisplayMessage( g_hModule, MSG_IP_NO_ENTRIES ); } } // // Enumerate the scopes // for ( dwCnt = 0; dwCnt < ulNumScopes; dwCnt++ ) { pScope = &pScopes[dwCnt]; strcpy( szAddr1, inet_ntoa( *((struct in_addr *) &pScope->ipGroupAddress) ) ); strcpy( szAddr2, inet_ntoa( *((struct in_addr *) &pScope->ipGroupMask) ) ); MakePrefixStringW(snScopeNameBuffer, pScope->ipGroupAddress, pScope->ipGroupMask); if (hFile) { PWCHAR pwszQuoted = MakeQuotedString( (pScope->ulNumNames)? pScope->snScopeNameBuffer : snScopeNameBuffer ); DisplayMessageT( DMP_SCOPE_INFO, szAddr1, szAddr2, pwszQuoted ); FreeQuotedString(pwszQuoted); } else { DisplayMessage( g_hModule, MSG_RTR_SCOPE_INFO, szAddr1, szAddr2, (pScope->ulNumNames)? pScope->snScopeNameBuffer : snScopeNameBuffer ); } } dwRes = NO_ERROR; if (pScopes) FREE(pScopes); if (pScopesBuffer) FREE(pScopesBuffer); } while ( FALSE ); return dwRes; } DWORD HandleIpShowScope( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) /*++ Routine Description: Arguments: ppwcArguments - Argument array dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg Return Value: NO_ERROR --*/ { return ShowScopes(0); } DWORD DeleteBoundary( IN DWORD dwDelInd, IN PBYTE pib, OUT PBYTE *ppibNew, IN OUT DWORD *pdwCount ) /*++ Description: Creates a new info block header which does not include the boundary with the specified index. Caller is responsible for freeing buffer returned. Called by: UpdateBoundaryBlock() --*/ { DWORD dwInd = 0, dwCnt = 0, dwCnt0 = 0, dwSize = 0, dwRes = NO_ERROR; LPBYTE pbDst = (LPBYTE) NULL, pbSrc = (LPBYTE) NULL; PRTR_INFO_BLOCK_HEADER pibh = (PRTR_INFO_BLOCK_HEADER) NULL; PMIB_BOUNDARYROW pimbSrc = (PMIB_BOUNDARYROW) NULL; PMIB_BOUNDARYROW pimbDst = (PMIB_BOUNDARYROW) NULL; // // Create new info block with boundary removed. // dwSize = (*pdwCount - 1) * sizeof( MIB_BOUNDARYROW ); if (dwSize is 0) { *ppibNew = NULL; *pdwCount = 0; return NO_ERROR; } *ppibNew = MALLOC( dwSize ); if ( *ppibNew == NULL ) { DisplayMessage( g_hModule, MSG_IP_NOT_ENOUGH_MEMORY ); return ERROR_NOT_ENOUGH_MEMORY; } // // Copy boundaries, skip boundary to be deleted // pimbDst = (PMIB_BOUNDARYROW) *ppibNew; pimbSrc = (PMIB_BOUNDARYROW) pib; for ( dwCnt = 0, dwCnt0 = 0; dwCnt < *pdwCount; dwCnt++ ) { if ( dwCnt == dwDelInd ) { continue; } pimbDst[ dwCnt0 ] = pimbSrc[ dwCnt ]; dwCnt0++; } (*pdwCount)--; return NO_ERROR; } DWORD AddBoundary ( IN PBYTE pib, OUT PBYTE *ppibNew, IN OUT DWORD *pdwCount ) /*++ Description: Creates a new info block which includes a boundary for the scope identified by g_ipGrpAddr/g_ipGrpMask. Caller is responsible for freeing buffer returned. Called by: UpdateBoundaryBlock() --*/ { DWORD dwRes = NO_ERROR, dwInd = 0, dwSize = 0; LPBYTE pbDst = (LPBYTE) NULL, pbSrc = (LPBYTE) NULL; PMIB_BOUNDARYROW pimb = (PMIB_BOUNDARYROW ) NULL; dwRes = VerifyBoundaryPrefix(g_ipGrpAddr, g_ipGrpMask); if (dwRes) { return NO_ERROR; } do { *ppibNew = NULL; // // If this is the first boundary, create info block // with an extra TocEntry. // dwSize = (*pdwCount + 1) * sizeof( MIB_BOUNDARYROW ); *ppibNew = MALLOC( dwSize ); if ( *ppibNew == NULL ) { DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY ); dwRes = ERROR_NOT_ENOUGH_MEMORY; break; } pbDst = *ppibNew; CopyMemory( pbDst, pib, (*pdwCount) * sizeof(MIB_BOUNDARYROW) ); pbDst += (*pdwCount) * sizeof(MIB_BOUNDARYROW); (*pdwCount)++; pimb = (PMIB_BOUNDARYROW) pbDst; pimb-> dwGroupAddress = g_ipGrpAddr; pimb-> dwGroupMask = g_ipGrpMask; pbDst += sizeof( MIB_BOUNDARYROW ); } while ( FALSE ); return dwRes; } BOOL IsBoundaryPresent( IN IPV4_ADDRESS ipGroupAddress, IN IPV4_ADDRESS ipGroupMask, IN PMIB_BOUNDARYROW pimb, IN DWORD dwNumBoundaries, OUT PDWORD pdwInd ) /*++ Returns: TRUE if present, and sets dwInd to index FALSE if not present, and sets dwInd to -1 Called by: UpdateBoundaryBlock() --*/ { DWORD dwInd = 0; *pdwInd = (DWORD) -1; for ( dwInd = 0; dwInd < dwNumBoundaries; dwInd++, pimb++ ) { if ( pimb-> dwGroupAddress != ipGroupAddress || pimb-> dwGroupMask != ipGroupMask ) { continue; } *pdwInd = dwInd; return TRUE; } return FALSE; } DWORD UpdateBoundaryBlock( IN DWORD dwAction, IN PBYTE pib, OUT PBYTE *ppibNew, IN OUT DWORD *pdwBlkSize, IN OUT DWORD *pdwCount, OUT BOOL *pbChanged ) /*++ Description: Caller is responsible for freeing buffer returned. Called by: IpAddDelBoundary(), DeleteBoundaryFromInterface() --*/ { DWORD dwRes = NO_ERROR, dwInd = 0, dwInd0 = 0; BOOL bBoFound = FALSE; PMIB_BOUNDARYROW pimb = (PMIB_BOUNDARYROW) NULL; *pbChanged = FALSE; do { *ppibNew = NULL; // // Find if specified boundary is present // bBoFound = IsBoundaryPresent( g_ipGrpAddr, g_ipGrpMask, (PMIB_BOUNDARYROW)pib, *pdwCount, &dwInd0 ); // // Update the boundary infoblock. // switch ( dwAction ) { case ADD_BOUNDARY: // // If boundary is not present, add it. Else return error. // if ( !bBoFound ) { dwRes = AddBoundary( pib, ppibNew, pdwCount ); *pdwBlkSize = sizeof(MIB_BOUNDARYROW); *pbChanged = TRUE; } else { dwRes = ERROR_OBJECT_ALREADY_EXISTS; } break; case DELETE_BOUNDARY: // // Delete boundary only if present. // if ( bBoFound ) { dwRes = DeleteBoundary( dwInd0, pib, ppibNew, pdwCount ); *pbChanged = TRUE; } // If not present, return success but don't set the changed flag. break; } } while ( FALSE ); return dwRes; } DWORD IpAddDelBoundary( DWORD dwAction, PWCHAR *ppwcArguments, DWORD dwCurrentIndex, DWORD dwArgCount ) { DWORD dwErr; TAG_TYPE pttTags[] = {{TOKEN_NAME, TRUE, FALSE}, {TOKEN_GROUP_ADDRESS, FALSE,FALSE}, {TOKEN_GROUP_MASK, FALSE,FALSE}, {TOKEN_SCOPE_NAME, FALSE,FALSE}, }; WCHAR rgwcIfName[MAX_INTERFACE_NAME_LEN + 1]; DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)]; IPV4_ADDRESS ipGroup, ipMask; DWORD dwBlkSize, dwCount, dwIfType, i, dwNumParsed; PBYTE pib, pibNew = NULL; BOOL bChanged; // Do generic processing dwErr = PreHandleCommand( ppwcArguments, dwCurrentIndex, dwArgCount, pttTags, sizeof(pttTags)/sizeof(TAG_TYPE), 2, 3, rgdwTagType ); if (dwErr) { return dwErr; } g_ipGrpAddr = g_ipGrpMask = 0; for(i = 0; i < dwArgCount - dwCurrentIndex; i ++) { switch (rgdwTagType[i]) { case 0 : // NAME { GetInterfaceName(ppwcArguments[i + dwCurrentIndex], rgwcIfName, sizeof(rgwcIfName), &dwNumParsed); break; } case 1: // GRPADDR { dwErr = GetIpPrefix(ppwcArguments[i + dwCurrentIndex], &g_ipGrpAddr, &g_ipGrpMask); if (!((dwErr is ERROR_INVALID_PARAMETER) && (dwAction is DELETE_BOUNDARY))) { break; } // FALLTHROUGH } case 3: // SCOPENAME { dwErr = ScopeNameToPrefix( ppwcArguments[i + dwCurrentIndex], &g_ipGrpAddr, &g_ipGrpMask ); if (dwErr is ERROR_MORE_DATA) { DisplayMessage( g_hModule, EMSG_AMBIGUOUS_SCOPE_NAME, ppwcArguments[i + dwCurrentIndex]); return NO_ERROR; } break; } case 2: // GRPMASK { dwErr = GetIpMask(ppwcArguments[i + dwCurrentIndex], &g_ipGrpMask); if (dwErr is ERROR_INVALID_PARAMETER) { DisplayMessage( g_hModule, MSG_IP_BAD_IP_ADDR, ppwcArguments[i + dwCurrentIndex]); DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE, pttTags[rgdwTagType[i]].pwszTag, ppwcArguments[i + dwCurrentIndex]); return NO_ERROR; } break; } } } if (dwErr isnot NO_ERROR) { return dwErr; } if (!g_ipGrpAddr || !g_ipGrpMask) { return ERROR_INVALID_SYNTAX; } do { dwErr = IpmontrGetInfoBlockFromInterfaceInfo( rgwcIfName, IP_MCAST_BOUNDARY_INFO, &pib, &dwBlkSize, &dwCount, &dwIfType ); if (dwErr is ERROR_NOT_FOUND) { // // No info of this type is currently present // dwErr = NO_ERROR; dwCount = 0; } if (dwErr isnot NO_ERROR) break; dwErr = UpdateBoundaryBlock( dwAction, pib, &pibNew, &dwBlkSize, &dwCount, &bChanged ); if (dwErr isnot NO_ERROR) break; if (bChanged) { dwErr = IpmontrSetInfoBlockInInterfaceInfo( rgwcIfName, IP_MCAST_BOUNDARY_INFO, pibNew, dwBlkSize, dwCount ); } } while (FALSE); if (pib) FREE(pib); if (pibNew) FREE(pibNew); return dwErr; } DWORD HandleIpAddBoundary( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) /*++ Routine Description: Arguments: ppwcArguments - Argument array dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg Return Value: NO_ERROR --*/ { return IpAddDelBoundary( ADD_BOUNDARY, ppwcArguments, dwCurrentIndex, dwArgCount ); } DWORD HandleIpDelBoundary( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) /*++ Routine Description: Arguments: ppwcArguments - Argument array dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg Return Value: NO_ERROR --*/ { return IpAddDelBoundary( DELETE_BOUNDARY, ppwcArguments, dwCurrentIndex, dwArgCount ); } DWORD ShowBoundaryInfoForInterface( IN HANDLE hFile, IN LPCWSTR pwszIfName, OUT PDWORD pdwNumRows ) /*++ Called by: ShowBoundaryInfo() --*/ { DWORD dwErr, dwBlkSize, dwCount, dwIfType, dwNumParsed, dwInd = 0, dwCnt = 0, dwSize = 0, dwGlobalSize = 0, dwIfLen = 0; WCHAR wszIfDesc[MAX_INTERFACE_NAME_LEN + 1]; ULONG ulNumScopes = 0; CHAR szAddr1[ ADDR_LENGTH ], szAddr2[ ADDR_LENGTH ]; HANDLE hIfTransport = (HANDLE) NULL, hTransport = (HANDLE) NULL; PRTR_INFO_BLOCK_HEADER pibhIfInfo = (PRTR_INFO_BLOCK_HEADER) NULL, pibhGlobalInfo = (PRTR_INFO_BLOCK_HEADER) NULL; PMIB_BOUNDARYROW pimb; PSCOPE_ENTRY pScope, pScopes; PBYTE pScopesBuffer; SCOPE_NAME_BUFFER snScopeNameBuffer; do { dwErr = IpmontrGetInfoBlockFromInterfaceInfo( pwszIfName, IP_MCAST_BOUNDARY_INFO, (PBYTE*)&pimb, &dwBlkSize, &dwCount, &dwIfType ); if (dwErr is ERROR_NOT_FOUND) dwErr = NO_ERROR; if (dwErr isnot NO_ERROR) return dwErr; if ( !dwCount ) break; dwErr = GetInterfaceDescription(pwszIfName, wszIfDesc, &dwNumParsed); if (!dwNumParsed) { wcscpy(wszIfDesc, pwszIfName); } dwIfLen = wcslen(wszIfDesc); // // Retrieve the list of scopes in pScopes[] // pScopes = GetScopes( &ulNumScopes, &pScopesBuffer ); // // Enumerate the boundaries // for ( dwCnt = 0; dwCnt < dwCount; dwCnt++ ) { pScope = FindScopeByPrefix( pimb[dwCnt].dwGroupAddress, pimb[dwCnt].dwGroupMask, pScopes, ulNumScopes ); strcpy( szAddr1, inet_ntoa( *((struct in_addr *) &pimb[dwCnt].dwGroupAddress) ) ); strcpy( szAddr2, inet_ntoa( *((struct in_addr *) &pimb[dwCnt].dwGroupMask) ) ); // Copy prefix to snScopeNameBuffer MakePrefixStringW(snScopeNameBuffer, pimb[dwCnt].dwGroupAddress, pimb[dwCnt].dwGroupMask); if (hFile) { PWCHAR pwszQuoted = MakeQuotedString(wszIfDesc); DisplayMessageT( DMP_BOUNDARY_INFO, pwszQuoted, szAddr1, szAddr2, (pScope && pScope->ulNumNames)? pScope->snScopeNameBuffer : snScopeNameBuffer ); FreeQuotedString(pwszQuoted); } else { if ( !*pdwNumRows ) { DisplayMessage( g_hModule, MSG_RTR_BOUNDARY_HDR ); } if (dwIfLen <= 15) { DisplayMessage( g_hModule, MSG_RTR_BOUNDARY_INFO_2, wszIfDesc, szAddr1, szAddr2, (pScope && pScope->ulNumNames)? pScope->snScopeNameBuffer : snScopeNameBuffer ); } else { DisplayMessage( g_hModule, MSG_RTR_BOUNDARY_INFO_0, wszIfDesc ); DisplayMessage( g_hModule, MSG_RTR_BOUNDARY_INFO_1, szAddr1, szAddr2, (pScope && pScope->ulNumNames)? pScope->snScopeNameBuffer : snScopeNameBuffer ); } } (*pdwNumRows) ++; } dwErr = NO_ERROR; if (pScopes) FREE(pScopes); if (pScopesBuffer) FREE(pScopesBuffer); } while ( FALSE ); if ( pimb ) { FREE(pimb); } return dwErr; } DWORD HandleIpShowBoundary( IN LPCWSTR pwszMachine, IN OUT LPWSTR *ppwcArguments, IN DWORD dwCurrentIndex, IN DWORD dwArgCount, IN DWORD dwFlags, IN LPCVOID pvData, OUT BOOL *pbDone ) /*++ Routine Description: Arguments: ppwcArguments - Argument array dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg Return Value: NO_ERROR --*/ { DWORD dwErr, dwTotal; TAG_TYPE pttTags[] = {{TOKEN_NAME,FALSE,FALSE}}; WCHAR rgwcIfName[MAX_INTERFACE_NAME_LEN + 1]; DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)]; DWORD dwBlkSize, dwCount, dwIfType, i, dwNumParsed; PBYTE pib, pibNew = NULL; PMPR_INTERFACE_0 pmi0; DWORD dwNumRows = 0; // Do generic processing dwErr = PreHandleCommand( ppwcArguments, dwCurrentIndex, dwArgCount, pttTags, sizeof(pttTags)/sizeof(TAG_TYPE), 0, 1, rgdwTagType ); if (dwErr) { return dwErr; } // If interface specified, show boundaries for specified interface only. if (dwArgCount > dwCurrentIndex) { GetInterfaceName( ppwcArguments[dwCurrentIndex], rgwcIfName, sizeof(rgwcIfName), &dwNumParsed ); dwErr = ShowBoundaryInfoForInterface( 0, rgwcIfName, &dwNumRows ); if (!dwNumRows) { DisplayMessage( g_hModule, MSG_IP_NO_ENTRIES ); } return dwErr; } // No Interface specified. Enumerate interfaces and show // boundaries for each interface. // // No interface name specified. List all interfaces under IP // dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0, &dwCount, &dwTotal); if (dwErr isnot NO_ERROR) { DisplayError(g_hModule, dwErr); return dwErr; } for ( i = 0; i < dwCount && dwErr is NO_ERROR; i++) { dwErr = ShowBoundaryInfoForInterface( 0, pmi0[i].wszInterfaceName, &dwNumRows ); if (dwErr is ERROR_NO_SUCH_INTERFACE) { dwErr = NO_ERROR; } } if (!dwNumRows) { DisplayMessage( g_hModule, MSG_IP_NO_ENTRIES ); } return dwErr; } //---------------------------------------------------------------------------- // PrintScope // // //---------------------------------------------------------------------------- static VOID PrintScope( PMIB_OPAQUE_INFO prpcInfo, PDWORD pdwLastAddr, PDWORD pdwLastMask ) { TCHAR ptszAddr[ ADDR_LENGTH + 1 ], ptszMask[ ADDR_LENGTH + 1 ], ptszBuffer[ MAX_SCOPE_NAME_LEN + 40 ]; PMIB_IPMCAST_SCOPE pmims; // // get scope // pmims = (PMIB_IPMCAST_SCOPE) prpcInfo->rgbyData; *pdwLastAddr = pmims-> dwGroupAddress; MakeUnicodeIpAddr(ptszAddr, inet_ntoa(*((struct in_addr *)(&pmims-> dwGroupAddress)))); *pdwLastMask = pmims-> dwGroupMask; MakeUnicodeIpAddr(ptszMask, inet_ntoa(*((struct in_addr *)(&pmims-> dwGroupMask)))); _stprintf(ptszBuffer, _T("%-15.15s %-15.15s %s"), ptszAddr, ptszMask, pmims-> snNameBuffer ); DisplayMessage( g_hModule, MSG_MIB_SCOPE_INFO, ptszBuffer ); return; } //---------------------------------------------------------------------------- // PrintBoundary // // //---------------------------------------------------------------------------- static VOID PrintBoundary( MIB_SERVER_HANDLE hMibServer, PMIB_OPAQUE_INFO prpcInfo, PDWORD pdwLastIfIndex, PDWORD pdwLastAddr, PDWORD pdwLastMask ) { WCHAR wszBuffer[MAX_INTERFACE_NAME_LEN+1]; TCHAR ptszAddr[ ADDR_LENGTH + 1 ], ptszMask[ ADDR_LENGTH + 1 ]; PMIB_IPMCAST_BOUNDARY pmims; // // get boundary // pmims = (PMIB_IPMCAST_BOUNDARY) prpcInfo->rgbyData; *pdwLastIfIndex = pmims-> dwIfIndex; *pdwLastAddr = pmims-> dwGroupAddress; MakeUnicodeIpAddr(ptszAddr, inet_ntoa(*((struct in_addr *)(&pmims-> dwGroupAddress)))); *pdwLastMask = pmims-> dwGroupMask; MakeUnicodeIpAddr(ptszMask, inet_ntoa(*((struct in_addr *)(&pmims-> dwGroupMask)))); IpmontrGetFriendlyNameFromIfIndex( hMibServer, pmims->dwIfIndex, wszBuffer, sizeof(wszBuffer) ); DisplayMessageToConsole( g_hModule, g_hConsole, MSG_MIB_BOUNDARY_INFO, ptszAddr, ptszMask, wszBuffer ); return; } #if 0 //---------------------------------------------------------------------------- // GetPrintScopeInfo // //---------------------------------------------------------------------------- DWORD GetPrintScopeInfo( MIB_SERVER_HANDLE hMIBServer ) { DWORD dwErr, dwOutEntrySize = 0, dwQuerySize, dwLastAddr = 0, dwLastMask = 0, i; PMIB_OPAQUE_INFO pRpcInfo = NULL; PMIB_IPMCAST_SCOPE pmims = NULL; PMIB_OPAQUE_QUERY pQuery; do { // // allocate and setup query structure // dwQuerySize = sizeof( MIB_OPAQUE_QUERY ) + sizeof(DWORD); pQuery = (PMIB_OPAQUE_QUERY) HeapAlloc( GetProcessHeap(), 0, dwQuerySize ); if ( pQuery == NULL ) { dwErr = ERROR_NOT_ENOUGH_MEMORY; DisplayMessage( g_hModule, ERROR_CONFIG, dwErr ); break; } pQuery->dwVarId = MCAST_SCOPE; for( i = 0; i < 2; i++ ) { pQuery->rgdwVarIndex[i] = 0; } // // get first scope // dwErr = MibGetFirst( PID_IP, IPRTRMGR_PID, (PVOID) pQuery, dwQuerySize, (PVOID *) &pRpcInfo, &dwOutEntrySize ); if ( dwErr != NO_ERROR ) { DisplayError( g_hModule, dwErr ); break; } // // if no scopes are present print a message to tell the user // pmims = (PMIB_IPMCAST_SCOPE)( pRpcInfo->rgbyData ); #if 0 if ( pTable->dwNumEntries is 0 ) { // // no scopes present. // DisplayMessage( g_hModule, MSG_MIB_NO_SCOPES ); break; } #endif // // print the scope // DisplayMessage( g_hModule, MSG_MIB_SCOPE_HDR ); PrintScope( pRpcInfo, &dwLastAddr, &dwLastMask ); MprAdminMIBBufferFree( pRpcInfo ); pRpcInfo = NULL; dwOutEntrySize = 0; // // while there are more scopes // get next scope // print it. // pQuery->rgdwVarIndex[ 0 ] = dwLastAddr; pQuery->rgdwVarIndex[ 1 ] = dwLastMask; while ( ( dwErr = MibGetNext( PID_IP, IPRTRMGR_PID, (PVOID) pQuery, dwQuerySize, (PVOID *) &pRpcInfo, &dwOutEntrySize ) ) == NO_ERROR ) { // // if no scopes are present quit // pmims = (PMIB_IPMCAST_SCOPE)( pRpcInfo->rgbyData ); #if 0 pTable = (PMIB_IPMCAST_SCOPE)( pRpcInfo->rgbyData ); if ( pTable->dwNumEntries is 0 ) { break; } #endif // // print the scope // PrintScope( pRpcInfo, &dwLastAddr, &dwLastMask ); MprAdminMIBBufferFree( pRpcInfo ); pRpcInfo = NULL; dwOutEntrySize = 0; // // set up the next query // pQuery->rgdwVarIndex[ 0 ] = dwLastAddr; pQuery->rgdwVarIndex[ 1 ] = dwLastMask; } if ( dwErr != NO_ERROR ) { DisplayMessage( g_hModule, ERROR_ADMIN, dwErr ); } } while ( FALSE ); return dwErr; } #endif //---------------------------------------------------------------------------- // GetPrintBoundaryInfo // //---------------------------------------------------------------------------- DWORD GetPrintBoundaryInfo( MIB_SERVER_HANDLE hMIBServer ) { DWORD dwErr, dwOutEntrySize = 0, dwQuerySize, dwLastIfIndex = 0, dwLastAddr = 0, dwLastMask = 0, i; PMIB_OPAQUE_INFO pRpcInfo = NULL; PMIB_IPMCAST_BOUNDARY pmims = NULL; PMIB_OPAQUE_QUERY pQuery; do { // // allocate and setup query structure // dwQuerySize = sizeof( MIB_OPAQUE_QUERY ) + 2 * sizeof(DWORD); pQuery = (PMIB_OPAQUE_QUERY) HeapAlloc( GetProcessHeap(), 0, dwQuerySize ); if ( pQuery == NULL ) { dwErr = ERROR_NOT_ENOUGH_MEMORY; DisplayMessage( g_hModule, ERROR_CONFIG, dwErr ); break; } pQuery->dwVarId = MCAST_BOUNDARY; for( i = 0; i < 2; i++ ) { pQuery->rgdwVarIndex[i] = 0; } // // get first boundary // dwErr = MibGetFirst( PID_IP, IPRTRMGR_PID, (PVOID) pQuery, dwQuerySize, (PVOID *) &pRpcInfo, &dwOutEntrySize ); if ( dwErr != NO_ERROR ) { DisplayError( g_hModule, dwErr ); break; } // // if no boundaries are present print a message to tell the user // pmims = (PMIB_IPMCAST_BOUNDARY)( pRpcInfo->rgbyData ); #if 0 if ( pTable->dwNumEntries is 0 ) { // // no boundaries present. // DisplayMessage( g_hModule, MSG_MIB_NO_BOUNDARIES ); break; } #endif // // print the boundary // DisplayMessageToConsole( g_hModule, g_hConsole, MSG_MIB_BOUNDARY_HDR ); PrintBoundary( hMIBServer, pRpcInfo, &dwLastIfIndex, &dwLastAddr, &dwLastMask ); MprAdminMIBBufferFree( pRpcInfo ); pRpcInfo = NULL; dwOutEntrySize = 0; // // while there are more boundaries // get next boundary // print it. // pQuery->rgdwVarIndex[ 0 ] = dwLastIfIndex; pQuery->rgdwVarIndex[ 1 ] = dwLastAddr; pQuery->rgdwVarIndex[ 2 ] = dwLastMask; while ( ( dwErr = MibGetNext( PID_IP, IPRTRMGR_PID, (PVOID) pQuery, dwQuerySize, (PVOID *) &pRpcInfo, &dwOutEntrySize ) ) == NO_ERROR ) { // // if no boundaries are present quit // pmims = (PMIB_IPMCAST_BOUNDARY)( pRpcInfo->rgbyData ); #if 0 pTable = (PMIB_IPMCAST_BOUNDARY)( pRpcInfo->rgbyData ); if ( pTable->dwNumEntries is 0 ) { break; } #endif // // print the boundary // PrintBoundary( hMIBServer, pRpcInfo, &dwLastIfIndex, &dwLastAddr, &dwLastMask ); MprAdminMIBBufferFree( pRpcInfo ); pRpcInfo = NULL; dwOutEntrySize = 0; // // set up the next query // pQuery->rgdwVarIndex[ 0 ] = dwLastIfIndex; pQuery->rgdwVarIndex[ 1 ] = dwLastAddr; pQuery->rgdwVarIndex[ 2 ] = dwLastMask; } if ( dwErr != NO_ERROR ) { DisplayMessage( g_hModule, ERROR_ADMIN, dwErr ); } } while ( FALSE ); return dwErr; }