/*++ Copyright (c) 1998 Microsoft Corporation Module Name: routing\monitor2\ip\utils.c Abstract: Utility functions Revision History: Anand Mahalingam 7/10/98 Created --*/ #include "precomp.h" #pragma hdrstop DWORD GetMibTagToken( IN LPWSTR *ppwcArguments, IN DWORD dwArgCount, IN DWORD dwNumIndices, OUT PDWORD pdwRR, OUT PBOOL pbIndex, OUT PDWORD pdwIndex ) /*++ Routine Description: Looks for indices and refresh rate arguments in the command. If index tag is present, it would be of the form index= index1 index2 .... The index= is removed by this function. So is rr= if it is there in the command. If pdwRR is 0 then, no refresh sought. Arguments: ppwcArguments - The argument array. Each argument has tag=value form dwCurrentIndex - ppwcArguments[dwCurrentIndex] is first arg. dwArgCount - ppwcArguments[dwArgCount - 1] is last arg. pttTagToken - Array of tag token ids that are allowed in the args dwNumTags - Size of pttTagToken pdwOut - Array identifying the type of each argument. Return Value: NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_INVALID_OPTION_TAG --*/ { DWORD i; BOOL bTag; if (dwArgCount is 0) { *pdwRR = 0; *pbIndex = FALSE; return NO_ERROR; } if (dwArgCount < dwNumIndices) { // // No index // *pbIndex = FALSE; if (dwArgCount > 1) { *pdwRR = 0; return ERROR_INVALID_PARAMETER; } // // No Index specified. Make sure refresh rate is specified // with tag. // if (_wcsnicmp(ppwcArguments[0],L"RR=",3) == 0) { // // get the refresh rate // *pdwRR = wcstoul(&ppwcArguments[0][3], NULL, 10); } else { return ERROR_INVALID_PARAMETER; } } else { // // Check for index tag // if (_wcsnicmp(ppwcArguments[0],L"INDEX=",6) == 0) { *pbIndex = TRUE; *pdwIndex = 0; // // remove tag and see if refresh rate is specified // wcscpy(ppwcArguments[0], &ppwcArguments[0][6]); if (dwArgCount > dwNumIndices) { // // Make sure that argument has RR tag // if (_wcsnicmp(ppwcArguments[dwNumIndices],L"RR=",3) == 0) { // // get the refresh rate // *pdwRR = wcstoul(&ppwcArguments[dwNumIndices][3], NULL , 10); } else { return ERROR_INVALID_PARAMETER; } } else { // // No refresh rate specified // *pdwRR = 0; return NO_ERROR; } } else { // // Not index tag, See if it has an RR tag // if (_wcsnicmp(ppwcArguments[0],L"RR=",3) == 0) { // // get the refresh rate // *pdwRR = wcstoul(&ppwcArguments[0][3], NULL , 10); // // See if the index follows // if (dwArgCount > dwNumIndices) { if (dwArgCount > 1) { if (_wcsnicmp(ppwcArguments[1],L"INDEX=",6) == 0) { wcscpy(ppwcArguments[1], &ppwcArguments[1][6]); *pbIndex = TRUE; *pdwIndex = 1; return NO_ERROR; } else { *pdwRR = 0; return ERROR_INVALID_PARAMETER; } } else { return NO_ERROR; } } } // // No RR Tag either // else if (dwArgCount > dwNumIndices) { // // Assume ppwcArguments[dwNumIndices] is the refresh rate // *pdwRR = wcstoul(ppwcArguments[dwNumIndices], NULL , 10); if (dwNumIndices != 0) { *pbIndex = TRUE; *pdwIndex = 0; } } else { // // only index present with no tag // *pbIndex = TRUE; *pdwIndex = 0; } } } return NO_ERROR; } DWORD GetIpPrefix( IN LPCWSTR ppwcArg, OUT PIPV4_ADDRESS pipAddress, OUT PIPV4_ADDRESS pipMask ) { CHAR pszIpAddr[ADDR_LENGTH+1], *p; DWORD dwDots; // Accept "default" as a special case if (MatchToken( ppwcArg, TOKEN_DEFAULT)) { *pipAddress = *pipMask = 0; return NO_ERROR; } // Make sure all characters are legal [/0-9.] if (ppwcArg[ wcsspn(ppwcArg, L"/0123456789.") ]) { return ERROR_INVALID_PARAMETER; } WideCharToMultiByte(GetConsoleOutputCP(), 0, ppwcArg, -1, pszIpAddr, ADDR_LENGTH, NULL, NULL); pszIpAddr[ADDR_LENGTH] = '\0'; p = strchr( pszIpAddr, '/' ); if (p) { ULONG ulLen = (atoi(p+1)); *pipMask = (ulLen)? htonl(~0 << (32 - ulLen)) : 0; *p = 0; } else { *pipMask = ~0; } // If less than three dots were specified, append .0 until there are for (dwDots=0, p=strchr(pszIpAddr, '.'); p; dwDots++,p=strchr(p+1,'.')); while (dwDots < 3) { strcat(pszIpAddr, ".0"); dwDots++; } *pipAddress = (DWORD) inet_addr(pszIpAddr); return NO_ERROR; } DWORD GetIpMask( IN LPCWSTR ppwcArg, OUT PIPV4_ADDRESS pipAddress ) /*++ Routine Description: Gets the ip address from the string. Arguments: pwszIpAddr - Ip address string pipAddress - IP address Return Value: NO_ERROR, ERROR_INVALID_PARAMETER --*/ { CHAR pszIpAddr[ADDR_LENGTH+1]; // Make sure all characters are legal [/0-9.] if (ppwcArg[ wcsspn(ppwcArg, L"/0123456789.") ]) { return ERROR_INVALID_PARAMETER; } WideCharToMultiByte(GetConsoleOutputCP(), 0, ppwcArg, -1, pszIpAddr, ADDR_LENGTH, NULL, NULL); pszIpAddr[ADDR_LENGTH] = '\0'; if (pszIpAddr[0] is '/') { ULONG ulLen = (atoi(pszIpAddr+1)); *pipAddress = (ulLen)? htonl(~0 << (32 - ulLen)) : 0; } else { *pipAddress = (DWORD) inet_addr(pszIpAddr); } return NO_ERROR; } DWORD GetIpAddress( IN LPCWSTR pwszArgument, OUT PIPV4_ADDRESS pipAddress ) /*++ Routine Description Gets the ip address from the string. Arguments pwszArgument argument specifing an ip address pipAddress ip address Return Value NO_ERROR if success Failure code o/w --*/ { CHAR pszAddress[ADDR_LENGTH + 1]; DWORD dwAddress = 0; PCHAR pcNext = NULL; ULONG ulCount = 0; // ensure all characters are legal [0-9.] if (pwszArgument[wcsspn(pwszArgument, L"0123456789.")]) return ERROR_INVALID_PARAMETER; // convert to an ansi string sprintf(pszAddress, "%S", pwszArgument); // ensure there are 3 '.' (periods) for (pcNext = pszAddress, ulCount = 0; *pcNext != '\0'; pcNext++) if (*pcNext is '.') ulCount++; if (ulCount != 3) return ERROR_INVALID_PARAMETER; dwAddress = (DWORD) inet_addr(pszAddress); // return an error if dwAddress is INADDR_NONE (255.255.255.255) // and the address specified isn't 255.255.255.255 (INADDR_NONE) if ((dwAddress is INADDR_NONE) and strcmp(pszAddress, "255.255.255.255")) return ERROR_INVALID_PARAMETER; *pipAddress = dwAddress; return NO_ERROR; } BYTE MaskToMaskLen( IPV4_ADDRESS dwMask ) { register int i; dwMask = ntohl(dwMask); for (i=0; i<32 && !(dwMask & (1<rgbyData); dwCount = pIfTable->dwNumEntries; *pdwIfIndex = 0; for (i=0; itable[i].wszName, pwszGuid)) { *pdwIfIndex = pIfTable->table[i].dwIndex; break; } } MprAdminMIBBufferFree( (PVOID) pRpcInfo ); return NO_ERROR; } DWORD GetGuidFromIfIndex( IN MIB_SERVER_HANDLE hMibServer, IN DWORD dwIfIndex, OUT LPWSTR pwszBuffer, IN DWORD dwBufferSize ) { MIB_OPAQUE_QUERY Query; PMIB_IFROW pIfRow; DWORD dwErr, dwOutEntrySize; PMIB_OPAQUE_INFO pRpcInfo; Query.dwVarId = IF_ROW; Query.rgdwVarIndex[0] = dwIfIndex; dwErr = MibGet( PID_IP, IPRTRMGR_PID, (PVOID) &Query, sizeof(Query), (PVOID *) &pRpcInfo, &dwOutEntrySize ); if (dwErr isnot NO_ERROR) { return dwErr; } pIfRow = (PMIB_IFROW)(pRpcInfo->rgbyData); wcscpy( pwszBuffer, pIfRow->wszName ); MprAdminMIBBufferFree( (PVOID) pRpcInfo ); return NO_ERROR; } DWORD IpmontrGetFriendlyNameFromIfIndex( IN MIB_SERVER_HANDLE hMibServer, IN DWORD dwIfIndex, OUT LPWSTR pwszBuffer, IN DWORD dwBufferSize ) /*++ Routine Description: Gets friendly Interface name from Interface index Arguments: hMibServer - Handle to the MIB server dwIfIndex - Interface index pwszBuffer - Buffer that will be holding the friendly interface name dwBufferSize - Size (in Bytes) of the pwszBuffer --*/ { WCHAR wszGuid[MAX_INTERFACE_NAME_LEN + 1]; DWORD dwErr; dwErr = GetGuidFromIfIndex(hMibServer, dwIfIndex, wszGuid, sizeof(wszGuid)); if (dwErr isnot NO_ERROR) { return dwErr; } return IpmontrGetFriendlyNameFromIfName( wszGuid, pwszBuffer, &dwBufferSize ); } DWORD IpmontrGetIfIndexFromFriendlyName( IN MIB_SERVER_HANDLE hMibServer, IN LPCWSTR pwszFriendlyName, OUT PDWORD pdwIfIndex ) { WCHAR wszGuid[MAX_INTERFACE_NAME_LEN + 1]; DWORD dwErr, dwSize = sizeof(wszGuid); dwErr = IpmontrGetIfNameFromFriendlyName( pwszFriendlyName, wszGuid, &dwSize ); if (dwErr isnot NO_ERROR) { return dwErr; } return GetIfIndexFromGuid( hMibServer, wszGuid, pdwIfIndex ); } DWORD IpmontrGetFriendlyNameFromIfName( IN LPCWSTR pwszName, OUT LPWSTR pwszBuffer, IN PDWORD pdwBufSize ) /*++ Description: Defines function to map a guid interface name to an unique descriptive name describing that interface. Arguments: pwszName - Buffer holding a Guid Interface Name pwszBuffer - Buffer to hold the Friendly Name pdwBufferSize - pointer to the Size (in Bytes) of the pwszBuffer --*/ { return NsGetFriendlyNameFromIfName( g_hMprConfig, pwszName, pwszBuffer, pdwBufSize ); } DWORD IpmontrGetIfNameFromFriendlyName( IN LPCWSTR pwszName, OUT LPWSTR pwszBuffer, IN PDWORD pdwBufSize ) /*++ Description: Defines function to map a friendly interface name to a guid interface name. Arguments: pwszName - Buffer holding a Friendly Interface Name pwszBuffer - Buffer to hold Guid Interface Name pdwBufferSize - pointer to the Size (in Bytes) of the pwszBuffer Returns: NO_ERROR, ERROR_NO_SUCH_INTERFACE --*/ { return NsGetIfNameFromFriendlyName( g_hMprConfig, pwszName, pwszBuffer, pdwBufSize ); } DWORD IpmontrCreateInterface( IN LPCWSTR pwszMachineName, IN LPCWSTR pwszInterfaceName, IN DWORD dwLocalAddress, IN DWORD dwRemoteAddress, IN BYTE byTtl ) /*++ Description: TODO This function is really really really ugly and does not belong in Netsh. There needs to be a system API to do this, but there isn't one right now so we have to workaround it by copying all this crud here. This code is stolen from netsh\if\routerdb.c RtrInterfaceAddIpip() which is also really really really ugly. --*/ { DWORD dwErr = ERROR_CAN_NOT_COMPLETE; GUID Guid; GUID *pGuid = &Guid; MPR_IPINIP_INTERFACE_0 NameInfo; MPR_INTERFACE_0 IfInfo; HANDLE hIfCfg; HANDLE hIfAdmin; IPINIP_CONFIG_INFO info; // Initialize // ZeroMemory(&IfInfo, sizeof(IfInfo)); IfInfo.fEnabled = TRUE; IfInfo.dwIfType = ROUTER_IF_TYPE_TUNNEL1; wcscpy(IfInfo.wszInterfaceName, pwszInterfaceName); info.dwLocalAddress = dwLocalAddress; info.dwRemoteAddress = dwRemoteAddress; info.byTtl = byTtl; dwErr = AddSetIpIpTunnelInfo(pwszInterfaceName, &info); if(dwErr isnot NO_ERROR) { // // Tear down the mapping // MprSetupIpInIpInterfaceFriendlyNameDelete(NULL, pGuid); } return dwErr; } DWORD IpmontrDeleteInterface( IN LPCWSTR pwszMachineName, IN LPCWSTR pwszInterfaceName ) /*++ Description: TODO This function is really really really ugly and does not belong in Netsh. There needs to be a system API to do this, but there isn't one right now so we have to workaround it by copying all this crud here. This code is stolen from netsh\if\routerdb.c RtrInterfaceDelete() which is also really really really ugly. Called by: HandleMsdpDeletePeer() --*/ { DWORD dwErr = ERROR_CAN_NOT_COMPLETE; DWORD dwSize; HANDLE hIfCfg, hIfAdmin; GUID Guid; MPR_INTERFACE_0 *pIfInfo; do { dwErr = MprConfigInterfaceGetHandle(g_hMprConfig, (LPWSTR)pwszInterfaceName, &hIfCfg); if(dwErr isnot NO_ERROR) { break; } dwErr = MprConfigInterfaceGetInfo(g_hMprConfig, hIfCfg, 0, (PBYTE *)&pIfInfo, &dwSize); if(dwErr isnot NO_ERROR) { break; } if(pIfInfo->dwIfType isnot ROUTER_IF_TYPE_TUNNEL1) { MprConfigBufferFree(pIfInfo); dwErr = ERROR_INVALID_PARAMETER; break; } dwErr = MprConfigInterfaceDelete(g_hMprConfig, hIfCfg); MprConfigBufferFree(pIfInfo); if(dwErr isnot NO_ERROR) { break; } dwErr = ConvertStringToGuid(pwszInterfaceName, (USHORT)(wcslen(pwszInterfaceName) * sizeof(WCHAR)), &Guid); if(dwErr isnot NO_ERROR) { break; } dwErr = MprSetupIpInIpInterfaceFriendlyNameDelete((LPWSTR)pwszMachineName, &Guid); if(IsRouterRunning()) { dwErr = MprAdminInterfaceGetHandle(g_hMprAdmin, (LPWSTR)pwszInterfaceName, &hIfAdmin, FALSE); if(dwErr isnot NO_ERROR) { break; } dwErr = MprAdminInterfaceDelete(g_hMprAdmin, hIfAdmin); } } while (FALSE); return dwErr; }