windows-nt/Source/XPSP1/NT/net/rras/netsh/ip/ipmon/utils.c
2020-09-26 16:20:57 +08:00

764 lines
18 KiB
C

/*++
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<<i)); i++);
return 32-i;
}
VOID
MakeAddressStringW(
OUT LPWSTR pwcPrefixStr,
IN IPV4_ADDRESS ipAddr
)
{
swprintf( pwcPrefixStr,
L"%d.%d.%d.%d",
PRINT_IPADDR(ipAddr) );
}
VOID
MakePrefixStringW(
OUT LPWSTR pwcPrefixStr,
IN IPV4_ADDRESS ipAddr,
IN IPV4_ADDRESS ipMask
)
{
swprintf( pwcPrefixStr,
L"%d.%d.%d.%d/%d",
PRINT_IPADDR(ipAddr),
MaskToMaskLen(ipMask) );
}
DWORD
GetIfIndexFromGuid(
IN MIB_SERVER_HANDLE hMibServer,
IN LPCWSTR pwszGuid,
OUT PDWORD pdwIfIndex
)
{
MIB_OPAQUE_QUERY Query;
PMIB_IFTABLE pIfTable;
DWORD dwErr, dwOutEntrySize;
PMIB_OPAQUE_INFO pRpcInfo;
DWORD dwCount, i;
Query.dwVarId = IF_TABLE;
Query.rgdwVarIndex[0] = 0;
dwErr = MibGet( PID_IP,
IPRTRMGR_PID,
(PVOID) &Query,
sizeof(Query),
(PVOID *) &pRpcInfo,
&dwOutEntrySize );
if (dwErr isnot NO_ERROR)
{
return dwErr;
}
pIfTable = (PMIB_IFTABLE)(pRpcInfo->rgbyData);
dwCount = pIfTable->dwNumEntries;
*pdwIfIndex = 0;
for (i=0; i<dwCount; i++)
{
if (!wcscmp(pIfTable->table[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;
}