windows-nt/Source/XPSP1/NT/net/rras/netsh/ipx/ipxmon/ipxmontr.c
2020-09-26 16:20:57 +08:00

1014 lines
22 KiB
C

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
routing\netsh\ipx\ipxmon\ipxmon.c
Abstract:
IPX Command dispatcher.
Revision History:
V Raman 11/25/98 Created
--*/
#include "precomp.h"
#pragma hdrstop
//
// Guid for IPMON.DLL
//
// {b1641451-84b8-11d2-b940-3078302c2030}
//
static const GUID g_MyGuid = IPXMONTR_GUID;
//
// Well known ROUTING guid
//
static const GUID g_RoutingGuid = ROUTING_GUID;
//
// IPX monitor version
//
#define IPX_HELPER_VERSION 1
//
// random wrapper macros
//
#define MALLOC(x) HeapAlloc( GetProcessHeap(), 0, x )
#define REALLOC(x,y) HeapReAlloc( GetProcessHeap(), 0, x, y )
#define FREE(x) HeapFree( GetProcessHeap(), 0, x )
//
// The table of Add, Delete, Set and Show Commands for IPX RTR MGR
// To add a command to one of the command groups, just add the
// CMD_ENTRY to the correct table. To add a new cmd group, create its
// cmd table and then add the group entry to group table
//
//
// The commands are prefix-matched with the command-line, in sequential
// order. So a command like 'ADD INTERFACE FILTER' must come before
// the command 'ADD INTERFACE' in the table. Likewise,
// a command like 'ADD ROUTE' must come before the command
// 'ADD ROUTEPREF' in the table.
//
CMD_ENTRY g_IpxAddCmdTable[] =
{
CREATE_CMD_ENTRY( IPX_ADD_ROUTE, HandleIpxAddRoute),
CREATE_CMD_ENTRY( IPX_ADD_SERVICE, HandleIpxAddService ),
CREATE_CMD_ENTRY( IPX_ADD_FILTER, HandleIpxAddFilter ),
CREATE_CMD_ENTRY( IPX_ADD_INTERFACE, HandleIpxAddInterface )
};
CMD_ENTRY g_IpxDelCmdTable[] =
{
CREATE_CMD_ENTRY( IPX_DELETE_ROUTE, HandleIpxDelRoute ),
CREATE_CMD_ENTRY( IPX_DELETE_SERVICE, HandleIpxDelService ),
CREATE_CMD_ENTRY( IPX_DELETE_FILTER, HandleIpxDelFilter ),
CREATE_CMD_ENTRY( IPX_DELETE_INTERFACE, HandleIpxDelInterface )
};
CMD_ENTRY g_IpxSetCmdTable[] =
{
CREATE_CMD_ENTRY( IPX_SET_ROUTE, HandleIpxSetRoute ),
CREATE_CMD_ENTRY( IPX_SET_SERVICE, HandleIpxSetService ),
CREATE_CMD_ENTRY( IPX_SET_FILTER, HandleIpxSetFilter ),
CREATE_CMD_ENTRY( IPX_SET_INTERFACE, HandleIpxSetInterface ),
CREATE_CMD_ENTRY( IPX_SET_GLOBAL, HandleIpxSetLoglevel )
};
CMD_ENTRY g_IpxShowCmdTable[] =
{
CREATE_CMD_ENTRY( IPX_SHOW_ROUTE, HandleIpxShowRoute ),
CREATE_CMD_ENTRY( IPX_SHOW_SERVICE, HandleIpxShowService),
CREATE_CMD_ENTRY( IPX_SHOW_FILTER, HandleIpxShowFilter ),
CREATE_CMD_ENTRY( IPX_SHOW_INTERFACE, HandleIpxShowInterface ),
CREATE_CMD_ENTRY( IPX_SHOW_GLOBAL, HandleIpxShowLoglevel ),
CREATE_CMD_ENTRY( IPX_SHOW_ROUTETABLE, HandleIpxShowRouteTable ),
CREATE_CMD_ENTRY( IPX_SHOW_SERVICETABLE,HandleIpxShowServiceTable ),
};
CMD_GROUP_ENTRY g_IpxCmdGroups[] =
{
CREATE_CMD_GROUP_ENTRY( GROUP_ADD, g_IpxAddCmdTable ),
CREATE_CMD_GROUP_ENTRY( GROUP_DELETE, g_IpxDelCmdTable ),
CREATE_CMD_GROUP_ENTRY( GROUP_SET, g_IpxSetCmdTable ),
CREATE_CMD_GROUP_ENTRY( GROUP_SHOW, g_IpxShowCmdTable )
};
ULONG g_ulNumGroups = sizeof(g_IpxCmdGroups)/sizeof(CMD_GROUP_ENTRY);
//
// Top level commands
//
CMD_ENTRY g_IpxCmds[] =
{
CREATE_CMD_ENTRY( IPX_UPDATE, HandleIpxUpdate )
};
ULONG g_ulNumTopCmds = sizeof(g_IpxCmds)/sizeof(CMD_ENTRY);
//
// Handle to this DLL
//
HANDLE g_hModule;
//
// Handle to router being administered
//
HANDLE g_hMprConfig;
HANDLE g_hMprAdmin;
HANDLE g_hMIBServer;
//
// Commit mode
//
BOOL g_bCommit;
DWORD ParentVersion;
BOOL g_bIpxDirty = FALSE;
NS_CONTEXT_CONNECT_FN IpxConnect;
NS_CONTEXT_SUBENTRY_FN IpxSubEntry;
//
// Variable that stores whether or not the helper has been
// initialized
//
ULONG g_ulInitCount;
//
// Router name
//
PWCHAR g_pwszRouter = NULL;
//
// Prototype declarations for functions in this file
//
DWORD
WINAPI
IpxUnInit(
IN DWORD dwReserved
);
BOOL
IsHelpToken(
PWCHAR pwszToken
);
BOOL
IA64VersionCheck
(
IN UINT CIMOSType, // WMI: Win32_OperatingSystem OSType
IN UINT CIMOSProductSuite, // WMI: Win32_OperatingSystem OSProductSuite
IN LPCWSTR CIMOSVersion, // WMI: Win32_OperatingSystem Version
IN LPCWSTR CIMOSBuildNumber, // WMI: Win32_OperatingSystem BuildNumber
IN LPCWSTR CIMServicePackMajorVersion, // WMI: Win32_OperatingSystem ServicePackMajorVersion
IN LPCWSTR CIMServicePackMinorVersion, // WMI: Win32_OperatingSystem ServicePackMinorVersion
IN UINT CIMProcessorArchitecture, // WMI: Win32_Processor Architecture
IN DWORD dwReserved
)
{
if (CIMProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) // IA64=6 (x86 == 0)
return TRUE;
else
return FALSE;
}
DWORD
WINAPI
IpxStartHelper(
IN CONST GUID *pguidParent,
IN DWORD dwVersion
)
/*++
Routine Description :
Registers the contexts supported by this helper
Arguements :
pguidParent - NETSH guid
Return value :
Don't know
--*/
{
DWORD dwErr;
NS_CONTEXT_ATTRIBUTES attMyAttributes;
PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivContextAttributes;
pNsPrivContextAttributes = MALLOC(sizeof(NS_PRIV_CONTEXT_ATTRIBUTES));
if (!pNsPrivContextAttributes)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
ParentVersion = dwVersion;
ZeroMemory( &attMyAttributes, sizeof(NS_CONTEXT_ATTRIBUTES));
ZeroMemory(pNsPrivContextAttributes, sizeof(NS_PRIV_CONTEXT_ATTRIBUTES));
attMyAttributes.pwszContext = L"ipx";
attMyAttributes.guidHelper = g_MyGuid;
attMyAttributes.dwVersion = 1;
attMyAttributes.dwFlags = 0;
attMyAttributes.ulNumTopCmds = g_ulNumTopCmds;
attMyAttributes.pTopCmds = (CMD_ENTRY (*)[])&g_IpxCmds;
attMyAttributes.ulNumGroups = g_ulNumGroups;
attMyAttributes.pCmdGroups = (CMD_GROUP_ENTRY (*)[])&g_IpxCmdGroups;
attMyAttributes.pfnCommitFn = NULL;
attMyAttributes.pfnDumpFn = IpxDump;
attMyAttributes.pfnConnectFn= IpxConnect;
attMyAttributes.pfnOsVersionCheck = IA64VersionCheck;
pNsPrivContextAttributes->pfnEntryFn = NULL;
pNsPrivContextAttributes->pfnSubEntryFn = IpxSubEntry;
attMyAttributes.pReserved = pNsPrivContextAttributes;
dwErr = RegisterContext( &attMyAttributes );
return dwErr;
}
DWORD
WINAPI
InitHelperDll(
IN DWORD dwNetshVersion,
OUT PNS_DLL_ATTRIBUTES pDllTable
)
/*++
Routine Description :
initialize this helper DLL
Arguements :
pUtilityTable - List of helper functions from the SHELL
pDllTable - Callbacks into this helper DLL passed back to the shell
Return value :
NO_ERROR - Success
--*/
{
DWORD dwErr;
NS_HELPER_ATTRIBUTES attMyAttributes;
//
// See if this is the first time we are being called
//
if ( InterlockedIncrement( &g_ulInitCount ) isnot 1 )
{
return NO_ERROR;
}
//
// Connect to router config. Also serves as a check to
// see if the router is configured on the machine
//
dwErr = MprConfigServerConnect( NULL, &g_hMprConfig );
if( dwErr isnot NO_ERROR )
{
DisplayError( NULL, dwErr );
return dwErr;
}
pDllTable->dwVersion = NETSH_VERSION_50;
pDllTable->pfnStopFn = StopHelperDll;
//
// Register helpers
//
ZeroMemory( &attMyAttributes, sizeof(attMyAttributes) );
attMyAttributes.guidHelper = g_MyGuid;
attMyAttributes.dwVersion = IPX_HELPER_VERSION;
attMyAttributes.pfnStart = IpxStartHelper;
attMyAttributes.pfnStop = NULL;
RegisterHelper( &g_RoutingGuid, &attMyAttributes );
return NO_ERROR;
}
DWORD
WINAPI
StopHelperDll(
IN DWORD dwReserved
)
/*++
Routine Description :
Arguements :
Return value :
--*/
{
if ( InterlockedDecrement( &g_ulInitCount ) isnot 0 )
{
return NO_ERROR;
}
#if 0
IpxCommit(NETSH_FLUSH);
#endif
return NO_ERROR;
}
BOOL
WINAPI
IpxDllEntry(
HINSTANCE hInstDll,
DWORD fdwReason,
LPVOID pReserved
)
/*++
Routine Description :
Arguements :
Return value :
--*/
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
g_hModule = hInstDll;
DisableThreadLibraryCalls(hInstDll);
break;
}
case DLL_PROCESS_DETACH:
{
break;
}
default:
{
break;
}
}
return TRUE;
}
DWORD
ConnectToRouter(
IN LPCWSTR pwszRouter
)
{
DWORD rc, dwErr;
if (g_pwszRouter != pwszRouter)
{
if (g_hMprConfig)
{
MprConfigServerDisconnect(g_hMprConfig);
g_hMprConfig = NULL;
}
if (g_hMprAdmin)
{
MprAdminServerDisconnect(g_hMprAdmin);
g_hMprAdmin = NULL;
}
if (g_hMIBServer)
{
MprAdminMIBServerDisconnect(g_hMIBServer);
g_hMIBServer = NULL;
}
}
//
// Connect to router config if required
// (when is this ever required)
//
if ( !g_hMprConfig )
{
dwErr = MprConfigServerConnect( (LPWSTR)pwszRouter, &g_hMprConfig );
if ( dwErr isnot NO_ERROR )
{
return ERROR_CONNECT_REMOTE_CONFIG;
}
}
//
// Check to see if router is running. If so, get the handles
//
do
{
if ( MprAdminIsServiceRunning( (LPWSTR)pwszRouter ) )
{
if ( MprAdminServerConnect( (LPWSTR)pwszRouter, &g_hMprAdmin ) ==
NO_ERROR )
{
if ( MprAdminMIBServerConnect( (LPWSTR)pwszRouter, &g_hMIBServer ) ==
NO_ERROR )
{
// DEBUG("Got server handle");
break;
}
else
{
MprAdminServerDisconnect( g_hMprAdmin );
}
}
}
g_hMprAdmin = g_hMIBServer = NULL;
} while (FALSE);
return NO_ERROR;
}
DWORD WINAPI
IpxConnect(
IN LPCWSTR pwszRouter
)
{
// If context info is dirty, reregister it
if (g_bIpxDirty)
{
IpxStartHelper(NULL, ParentVersion);
}
return ConnectToRouter(pwszRouter);
}
BOOL
IsHelpToken(
PWCHAR pwszToken
)
/*++
Routine Description :
Arguements :
Return value :
--*/
{
if( MatchToken( pwszToken, CMD_IPX_HELP1 ) )
{
return TRUE;
}
if( MatchToken( pwszToken, CMD_IPX_HELP2 ) )
{
return TRUE;
}
return FALSE;
}
BOOL
IsReservedKeyWord(
PWCHAR pwszToken
)
/*++
Routine Description :
Arguements :
Return value :
--*/
{
return FALSE;
}
DWORD
MungeArguments(
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwArgCount,
OUT PBYTE *ppbNewArg,
OUT PDWORD pdwNewArgCount,
OUT PBOOL pbFreeArg
)
/*++
Routine Description :
To conform to the routemon style of command line, the netsh command line
is munged. Munging involves adding a space after the '=' for each
"Option=Value" pair on the command line to convert it to "Option= Value".
In addition, the first command line arguement is set to the process name
"netsh" and all the remaining arguements are shifted one down. Again
for conformance reasons.
Arguements :
ppwcArguments - Current argument list
dwArgCount - Number of args in ppwcArguments
pbNewArg - Pointer to a buffer that will contain the munged arglist
pdwNewArgCount - New argument count after munging
pbFreeArg - TRUE if pbNewArg needs to be freed by the invoker.
Return value :
NO_ERROR - Success
ERROR_NOT_ENOUGH_MEMORY - Memory alloc failed
--*/
{
DWORD dwIndex, dwInd, dwErr;
BOOL bPresent = FALSE;
PWCHAR *ppwcArgs;
*pbFreeArg = FALSE;
//
// Scan arguement list to see if any are of the form "Option=Value"
//
for ( dwIndex = 0; dwIndex < dwArgCount; dwIndex++ )
{
if ( wcsstr( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER ) )
{
//
// there is an = in this arguement
//
bPresent = TRUE;
break;
}
}
//
// if none of the args have an '=', then return the arg. list as is
//
if ( !bPresent )
{
*ppbNewArg = (PBYTE) ppwcArguments;
return NO_ERROR;
}
//
// Args. of the form "option=value" are present
//
ppwcArgs = (PWCHAR *) HeapAlloc(
GetProcessHeap(), 0, 2 * dwArgCount * sizeof( PWCHAR )
);
if ( ppwcArgs == NULL )
{
return ERROR_NOT_ENOUGH_MEMORY;
}
ZeroMemory( ppwcArgs, 2 * dwArgCount * sizeof( PWCHAR ) );
//
// Copy args that do not have an '=' as is
//
for ( dwInd = 0; dwInd < dwIndex; dwInd++ )
{
DWORD dwLen = ( wcslen( ppwcArguments[ dwInd ] ) + 1 ) * sizeof( WCHAR );
ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
GetProcessHeap(), 0,
( wcslen( ppwcArguments[ dwInd ] ) + 1 )
* sizeof( WCHAR )
);
if ( ppwcArgs[ dwInd ] == NULL )
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
wcscpy( ppwcArgs[ dwInd ], ppwcArguments[ dwInd ] );
}
//
// Convert args. of the form "option=value" to the form "option= value".
// The space is what its all about
//
for ( dwInd = dwIndex; dwIndex < dwArgCount; dwInd++, dwIndex++ )
{
//
// Check if this arg. has an '=' sign
//
if ( wcsstr( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER ) )
{
//
// arg is of the form "option=value"
//
// break it into 2 arguments of the form
// arg(i) == option=
// argv(i+1) == value
//
PWCHAR pw1, pw2;
DWORD dwLen;
pw1 = wcstok( ppwcArguments[ dwIndex ], NETSH_ARG_DELIMITER );
pw2 = wcstok( NULL, NETSH_ARG_DELIMITER );
dwLen = ( wcslen( pw1 ) + 2 ) * sizeof( WCHAR );
dwLen = ( wcslen( pw2 ) + 1 ) * sizeof( WCHAR );
ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
GetProcessHeap(), 0,
( wcslen( pw1 ) + 2 ) * sizeof( WCHAR )
);
ppwcArgs[ dwInd + 1] = (PWCHAR) HeapAlloc(
GetProcessHeap(), 0,
( wcslen( pw2 ) + 1 ) * sizeof( WCHAR )
);
if ( ( ppwcArgs[ dwInd ] == NULL ) ||
( ppwcArgs[ dwInd + 1 ] == NULL ) )
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
wcscpy( ppwcArgs[ dwInd ], pw1 );
wcscat( ppwcArgs[ dwInd++ ], NETSH_ARG_DELIMITER );
wcscpy( ppwcArgs[ dwInd ], pw2 );
(*pdwNewArgCount)++;
}
else
{
//
// no = in this arg, copy as is
//
ppwcArgs[ dwInd ] = (PWCHAR) HeapAlloc(
GetProcessHeap(), 0,
( wcslen( ppwcArguments[ dwIndex ] ) + 1 )
* sizeof( WCHAR )
);
if ( ppwcArgs[ dwInd ] == NULL )
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
wcscpy( ppwcArgs[ dwInd ], ppwcArguments[ dwIndex ] );
}
}
*pbFreeArg = TRUE;
*ppbNewArg = (PBYTE) ppwcArgs;
return NO_ERROR;
cleanup :
//
// Error. Free all allocations
//
for ( dwInd = 0; dwInd < 2 * dwArgCount; dwInd++ )
{
if ( ppwcArgs[ dwInd ] )
{
HeapFree( GetProcessHeap(), 0, ppwcArgs[ dwInd ] );
}
}
if ( ppwcArgs )
{
HeapFree( GetProcessHeap(), 0, ppwcArgs );
}
return dwErr;
}
VOID
FreeArgTable(
IN DWORD dwArgCount,
IN OUT LPWSTR *ppwcArgs
)
/*++
Routine Description :
Frees the allocations for the argument table
Arguments :
dwArgCount - number of arguments in ppwcArguments
ppwcArgs - Table of arguments
Return Value :
--*/
{
DWORD dwInd;
for ( dwInd = 0; dwInd < 2 * dwArgCount; dwInd++ )
{
if ( ppwcArgs[ dwInd ] )
{
HeapFree( GetProcessHeap(), 0, ppwcArgs[ dwInd ] );
}
}
if ( ppwcArgs )
{
HeapFree( GetProcessHeap(), 0, ppwcArgs );
}
}
DWORD
GetTagToken(
IN HANDLE hModule,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN PTAG_TYPE pttTagToken,
IN DWORD dwNumTags,
OUT PDWORD pdwOut
)
/*++
Routine Description:
Identifies each argument based on its tag. It assumes that each argument
has a tag. It also removes tag= from each argument.
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,j,len;
PWCHAR pwcTag,pwcTagVal,pwszArg;
BOOL bFound = FALSE;
//
// This function assumes that every argument has a tag
// It goes ahead and removes the tag.
//
for (i = dwCurrentIndex; i < dwArgCount; i++)
{
len = wcslen(ppwcArguments[i]);
if (len is 0)
{
//
// something wrong with arg
//
pdwOut[i] = (DWORD) -1;
continue;
}
pwszArg = HeapAlloc(GetProcessHeap(),0,(len + 1) * sizeof(WCHAR));
if (pwszArg is NULL)
{
DisplayError(g_hModule, ERROR_NOT_ENOUGH_MEMORY);
return ERROR_NOT_ENOUGH_MEMORY;
}
wcscpy(pwszArg, ppwcArguments[i]);
pwcTag = wcstok(pwszArg, NETSH_ARG_DELIMITER);
//
// Got the first part
// Now if next call returns NULL then there was no tag
//
pwcTagVal = wcstok((PWCHAR)NULL, NETSH_ARG_DELIMITER);
if (pwcTagVal is NULL)
{
// DisplayMessage(g_hModule, MSG_IP_TAG_NOT_PRESENT, ppwcArguments[i] );
HeapFree(GetProcessHeap(),0,pwszArg);
return ERROR_INVALID_PARAMETER;
}
//
// Got the tag. Now try to match it
//
bFound = FALSE;
pdwOut[i - dwCurrentIndex] = (DWORD) -1;
for ( j = 0; j < dwNumTags; j++)
{
if (MatchToken(pwcTag, pttTagToken[j].pwszTag))
{
//
// Tag matched
//
bFound = TRUE;
pdwOut[i - dwCurrentIndex] = j;
break;
}
}
if (bFound)
{
//
// Remove tag from the argument
//
wcscpy(ppwcArguments[i], pwcTagVal);
}
else
{
//DisplayMessage(g_hModule, MSG_IP_INVALID_TAG, pwcTag);
HeapFree(GetProcessHeap(),0,pwszArg);
return ERROR_INVALID_OPTION_TAG;
}
HeapFree(GetProcessHeap(),0,pwszArg);
}
return NO_ERROR;
}
DWORD WINAPI
IpxSubEntry(
IN const NS_CONTEXT_ATTRIBUTES *pSubContext,
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN PVOID pvData,
OUT LPWSTR pwcNewContext
)
{
DWORD dwErr,
dwNewArgCount = dwArgCount;
PWCHAR *ppwcNewArg = NULL;
BOOL bFreeNewArg;
PNS_PRIV_CONTEXT_ATTRIBUTES pNsPrivContextAttributes = pSubContext->pReserved;
dwErr = MungeArguments( ppwcArguments,
dwArgCount,
(PBYTE*) &ppwcNewArg,
&dwNewArgCount,
&bFreeNewArg );
if (dwErr isnot NO_ERROR )
{
return dwErr;
}
if ( (pNsPrivContextAttributes) && (pNsPrivContextAttributes->pfnEntryFn) )
{
dwErr = (*pNsPrivContextAttributes->pfnEntryFn)( pwszMachine,
ppwcNewArg,
dwNewArgCount,
dwFlags,
g_hMIBServer,
pwcNewContext );
}
else
{
dwErr = GenericMonitor(pSubContext,
pwszMachine,
ppwcNewArg,
dwNewArgCount,
dwFlags,
g_hMIBServer,
pwcNewContext );
}
if ( bFreeNewArg )
{
FreeArgTable( dwArgCount, ppwcNewArg );
}
return dwErr;
}