You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4693 lines
121 KiB
4693 lines
121 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
qosopt.c
|
|
|
|
Abstract:
|
|
|
|
Fns to parse QOS commands
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#pragma hdrstop
|
|
|
|
|
|
//
|
|
// Install, Uninstall Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosInstall(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for adding QOS global info
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR or Error Code
|
|
|
|
--*/
|
|
|
|
{
|
|
PBYTE pbInfoBlk;
|
|
DWORD dwSize, dwErr;
|
|
|
|
//
|
|
// No options expected for add command.
|
|
//
|
|
|
|
if (dwCurrentIndex != dwArgCount)
|
|
{
|
|
//
|
|
// No arguments specified
|
|
//
|
|
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
pbInfoBlk = NULL;
|
|
|
|
do
|
|
{
|
|
dwErr = MakeQosGlobalInfo( &pbInfoBlk, &dwSize);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Add Qos to global block
|
|
//
|
|
|
|
dwErr = IpmontrSetInfoBlockInGlobalInfo(MS_IP_QOSMGR,
|
|
pbInfoBlk,
|
|
dwSize,
|
|
1);
|
|
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
UpdateAllInterfaceConfigs();
|
|
}
|
|
}
|
|
while (FALSE);
|
|
|
|
HEAP_FREE_NOT_NULL(pbInfoBlk);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
DWORD
|
|
HandleQosUninstall(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for deleting QOS global info
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR or Error Code
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD dwErr;
|
|
|
|
//
|
|
// No options expected for add command.
|
|
//
|
|
|
|
if (dwCurrentIndex != dwArgCount)
|
|
{
|
|
//
|
|
// No arguments specified
|
|
//
|
|
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
dwErr = IpmontrDeleteProtocol(MS_IP_QOSMGR);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Add, Del, Show Child Helpers
|
|
//
|
|
|
|
|
|
//
|
|
// Set and Show Global Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosSetGlobal(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for setting QOS global info
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR or Error Code
|
|
|
|
--*/
|
|
{
|
|
DWORD dwBitVector;
|
|
DWORD dwErr, dwRes;
|
|
DWORD dwNumArg, i, j;
|
|
IPQOS_GLOBAL_CONFIG igcGlobalCfg;
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_LOG_LEVEL,FALSE,FALSE}};
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
dwBitVector = 0;
|
|
|
|
for ( i = 0; i < dwNumArg; i++)
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0 :
|
|
{
|
|
//
|
|
// Tag LOGLEVEL
|
|
//
|
|
|
|
TOKEN_VALUE rgEnums[] =
|
|
{{TOKEN_OPT_VALUE_NONE, IPQOS_LOGGING_NONE},
|
|
{TOKEN_OPT_VALUE_ERROR, IPQOS_LOGGING_ERROR},
|
|
{TOKEN_OPT_VALUE_WARN, IPQOS_LOGGING_WARN},
|
|
{TOKEN_OPT_VALUE_INFO, IPQOS_LOGGING_INFO}};
|
|
|
|
GET_ENUM_TAG_VALUE();
|
|
|
|
igcGlobalCfg.LoggingLevel = dwRes;
|
|
|
|
dwBitVector |= QOS_LOG_MASK;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
if (dwBitVector)
|
|
{
|
|
dwErr = UpdateQosGlobalConfig(&igcGlobalCfg,
|
|
dwBitVector);
|
|
}
|
|
}
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
HandleQosShowGlobal(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for showing QOS global info
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// Does not expect any arguments. If any are specified, report error.
|
|
//
|
|
|
|
if (dwCurrentIndex != dwArgCount)
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
return ShowQosGlobalInfo(NULL);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Add, Del, Set, Show If Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosAddIf(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for add interface
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
dwErr
|
|
|
|
--*/
|
|
{
|
|
WCHAR wszInterfaceName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
|
|
DWORD dwErr, dwIfType, dwBlkSize, dwBitVector = 0, dwCount;
|
|
IPQOS_IF_CONFIG ChangeCfg;
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// get optional parameters that are also being set
|
|
//
|
|
|
|
ZeroMemory(&ChangeCfg, sizeof(IPQOS_IF_CONFIG));
|
|
|
|
dwErr = GetQosSetIfOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
wszInterfaceName,
|
|
sizeof(wszInterfaceName),
|
|
&ChangeCfg,
|
|
&dwBitVector,
|
|
ADD_FLAG
|
|
);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
do
|
|
{
|
|
//
|
|
// make sure that the interface does not already exist in the config
|
|
//
|
|
{
|
|
PIPQOS_IF_CONFIG pTmpCfg;
|
|
|
|
dwErr = IpmontrGetInfoBlockFromInterfaceInfo(wszInterfaceName,
|
|
MS_IP_QOSMGR,
|
|
(PBYTE *) &pTmpCfg,
|
|
&dwBlkSize,
|
|
&dwCount,
|
|
&dwIfType);
|
|
|
|
if (dwErr is NO_ERROR && pTmpCfg != NULL)
|
|
{
|
|
HEAP_FREE(pTmpCfg);
|
|
|
|
DisplayMessage(g_hModule, EMSG_INTERFACE_EXISTS,
|
|
wszInterfaceName);
|
|
|
|
return ERROR_SUPPRESS_OUTPUT;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// check if Qos global info is set. else add Qos global info
|
|
//
|
|
{
|
|
PIPQOS_GLOBAL_CONFIG pGlobalConfig = NULL;
|
|
DWORD dwBlkSize, dwCount;
|
|
|
|
dwErr = IpmontrGetInfoBlockFromGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE *) &pGlobalConfig,
|
|
&dwBlkSize,
|
|
&dwCount);
|
|
|
|
HEAP_FREE_NOT_NULL(pGlobalConfig);
|
|
|
|
if ((dwErr is ERROR_NOT_FOUND) || (dwBlkSize == 0))
|
|
{
|
|
// create qos global info
|
|
|
|
dwErr = HandleQosInstall(pwszMachine,
|
|
NULL,
|
|
0,
|
|
0,
|
|
dwFlags,
|
|
hMibServer,
|
|
pbDone);
|
|
}
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// set the interface info
|
|
//
|
|
|
|
dwErr = UpdateQosInterfaceConfig(wszInterfaceName,
|
|
&ChangeCfg,
|
|
dwBitVector,
|
|
ADD_FLAG);
|
|
}
|
|
while (FALSE);
|
|
|
|
// no error message
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY: dwErr;
|
|
}
|
|
|
|
DWORD
|
|
HandleQosDelIf(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for del interface
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
WCHAR wszInterfaceName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
|
|
DWORD dwErr, dwIfType, dwBlkSize, dwBitVector = 0, dwCount;
|
|
IPQOS_IF_CONFIG ChangeCfg; //will not be used
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// get interface name.
|
|
//
|
|
|
|
ZeroMemory( &ChangeCfg, sizeof(IPQOS_IF_CONFIG) );
|
|
|
|
dwErr = GetQosSetIfOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
wszInterfaceName,
|
|
sizeof(wszInterfaceName),
|
|
&ChangeCfg,
|
|
&dwBitVector,
|
|
ADD_FLAG
|
|
);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// make sure that no other option is set.
|
|
//
|
|
if (dwBitVector)
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
//
|
|
// delete interface info
|
|
//
|
|
|
|
dwErr = IpmontrDeleteInfoBlockFromInterfaceInfo(wszInterfaceName,
|
|
MS_IP_QOSMGR);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY: dwErr;
|
|
}
|
|
|
|
DWORD
|
|
HandleQosSetIf(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for set interface
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
|
|
{
|
|
IPQOS_IF_CONFIG ChangeCfg; //no variable parts can be set
|
|
DWORD dwBitVector = 0,
|
|
dwErr = NO_ERROR;
|
|
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// get the optional interface parameters
|
|
//
|
|
|
|
ZeroMemory( &ChangeCfg, sizeof(IPQOS_IF_CONFIG) );
|
|
|
|
dwErr = GetQosSetIfOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
wszIfName,
|
|
sizeof(wszIfName),
|
|
&ChangeCfg,
|
|
&dwBitVector,
|
|
SET_FLAG
|
|
);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
if (dwBitVector)
|
|
{
|
|
//
|
|
// Call UpdateInterfaceCfg
|
|
//
|
|
|
|
dwErr = UpdateQosInterfaceConfig(wszIfName,
|
|
&ChangeCfg,
|
|
dwBitVector,
|
|
SET_FLAG);
|
|
}
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY: dwErr;
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleQosShowIf(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for showing QOS interface info
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
DWORD i, j, dwErr = NO_ERROR, dwNumOpt;
|
|
WCHAR wszInterfaceName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
|
|
DWORD dwNumArg,
|
|
dwBufferSize = sizeof(wszInterfaceName);
|
|
DWORD dwSize, dwRes;
|
|
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,FALSE,FALSE}};
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
if (dwCurrentIndex == dwArgCount) {
|
|
|
|
dwErr = ShowQosAllInterfaceInfo( NULL ) ;
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Parse command line
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, NUM_TAGS_IN_TABLE(pttTags),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
for ( i = 0; i < dwNumArg; i++)
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0 :
|
|
IpmontrGetIfNameFromFriendlyName(pptcArguments[i + dwCurrentIndex],
|
|
wszInterfaceName,&dwBufferSize);
|
|
|
|
break;
|
|
|
|
default:
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
dwErr = ShowQosInterfaceInfo(NULL, wszInterfaceName);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//
|
|
// Dump Handlers
|
|
//
|
|
|
|
|
|
DWORD
|
|
DumpQosInformation (
|
|
HANDLE hFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dumps Qos information to a text file
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//DisplayMessageT( DMP_QOS_HEADER );
|
|
DisplayMessage(g_hModule, MSG_QOS_HEADER);
|
|
DisplayMessageT( DMP_QOS_PUSHD );
|
|
DisplayMessageT( DMP_QOS_UNINSTALL );
|
|
|
|
//DisplayMessageT(DMP_QOS_GLOBAL_HEADER) ;
|
|
|
|
//
|
|
// dump qos global information
|
|
//
|
|
|
|
ShowQosGlobalInfo( hFile ) ;
|
|
|
|
//
|
|
// dump flowspecs at the end
|
|
// of the global information
|
|
//
|
|
|
|
ShowQosFlowspecs(hFile, NULL);
|
|
|
|
//
|
|
// dump qos objects that occur
|
|
// at the end of flowspec info
|
|
//
|
|
|
|
ShowQosObjects(hFile,
|
|
NULL,
|
|
QOS_OBJECT_END_OF_LIST);
|
|
|
|
//DisplayMessageT(DMP_QOS_GLOBAL_FOOTER);
|
|
|
|
//
|
|
// dump qos config for all interfaces
|
|
//
|
|
|
|
ShowQosAllInterfaceInfo( hFile );
|
|
|
|
DisplayMessageT( DMP_POPD );
|
|
//DisplayMessageT( DMP_QOS_FOOTER );
|
|
DisplayMessage( g_hModule, MSG_QOS_FOOTER );
|
|
|
|
return NO_ERROR ;
|
|
}
|
|
|
|
DWORD
|
|
QosDump(
|
|
PWCHAR pwszMachine,
|
|
WCHAR **ppwcArguments,
|
|
DWORD dwArgCount,
|
|
PVOID pvData
|
|
)
|
|
{
|
|
return DumpQosInformation((HANDLE) -1);
|
|
}
|
|
|
|
//
|
|
// Help Handlers
|
|
//
|
|
|
|
|
|
//
|
|
// Flowspec Add, Del, Set Handlers
|
|
//
|
|
|
|
|
|
DWORD
|
|
HandleQosAddFlowspec(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for adding flowspecs to the
|
|
global info.
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
return GetQosAddDelFlowspecOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
TRUE);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosDelFlowspec(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for deleting flowspecs from the
|
|
global info.
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
return GetQosAddDelFlowspecOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
FALSE);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosShowFlowspec(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for showing flowspecs in the
|
|
global info.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,FALSE,FALSE}};
|
|
PTCHAR pszFlowspec;
|
|
DWORD dwNumOpt, dwRes;
|
|
DWORD dwNumArg, i, j;
|
|
DWORD dwTagType, dwErr;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
if (dwCurrentIndex == dwArgCount)
|
|
{
|
|
//
|
|
// No arguments - show all flowspecs
|
|
//
|
|
|
|
pszFlowspec = NULL;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Get name of the flowspec to show
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
if (dwNumArg != 1)
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
pszFlowspec = pptcArguments[dwCurrentIndex];
|
|
}
|
|
|
|
return ShowQosFlowspecs(NULL, pszFlowspec);
|
|
}
|
|
|
|
|
|
//
|
|
// DsRule Add, Del, Show Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosAddDsRule(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for adding diffserv rules to the
|
|
diffserv maps in global info. If the diffserv
|
|
map in not already present, a new one will be
|
|
created when adding the first rule.
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
return GetQosAddDelDsRuleOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
TRUE);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosDelDsRule(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for deleting diffserv ruless from
|
|
an existing diffserv map in the global info. If
|
|
this is the last diffserv rule in the diffserv
|
|
map, the diffserv map is removed from the global
|
|
info.
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
return GetQosAddDelDsRuleOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
FALSE);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosShowDsMap(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for showing diffserv maps
|
|
in the global info.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return HandleQosShowGenericQosObject(QOS_OBJECT_DIFFSERV,
|
|
pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
pbDone);
|
|
}
|
|
|
|
//
|
|
// Flow Add, Del, Set Handlers
|
|
//
|
|
|
|
|
|
DWORD
|
|
HandleQosAddFlowOnIf(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for adding flows on an interface
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
return GetQosAddDelIfFlowOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
TRUE);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosDelFlowOnIf(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for deleting flows on an interface
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
return GetQosAddDelIfFlowOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
FALSE);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosShowFlowOnIf(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR wszInterfaceName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
|
|
DWORD dwBufferSize = sizeof(wszInterfaceName);
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,FALSE,FALSE},
|
|
{TOKEN_OPT_FLOW_NAME,FALSE,FALSE}};
|
|
PTCHAR pszIfName;
|
|
PTCHAR pszFlow;
|
|
DWORD dwNumOpt, dwRes;
|
|
DWORD dwNumArg, i, j;
|
|
DWORD dwErr;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
pszIfName = pszFlow = NULL;
|
|
|
|
if (dwCurrentIndex == dwArgCount)
|
|
{
|
|
//
|
|
// No arguments - show all flows on all interfaces
|
|
//
|
|
|
|
dwErr = NO_ERROR;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Get name of the flow to show
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
for ( i = 0; i < dwNumArg; i++ )
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0: // Interfacename
|
|
|
|
IpmontrGetIfNameFromFriendlyName(pptcArguments[i + dwCurrentIndex],
|
|
wszInterfaceName,
|
|
&dwBufferSize);
|
|
pszIfName = wszInterfaceName;
|
|
break;
|
|
|
|
case 1: // Flowname
|
|
|
|
pszFlow = pptcArguments[dwCurrentIndex + i];
|
|
break;
|
|
|
|
default:
|
|
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
dwErr = ShowQosFlows(NULL, pszIfName, pszFlow);
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//
|
|
// FlowspecOnFlow Add, Del Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosAddFlowspecOnIfFlow(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return GetQosAddDelFlowspecOnFlowOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
TRUE);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosDelFlowspecOnIfFlow(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return GetQosAddDelFlowspecOnFlowOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
FALSE);
|
|
}
|
|
|
|
//
|
|
// QosObject Del, Show Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosDelQosObject(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for deleting qos objects
|
|
in the global info.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,TRUE,FALSE}};
|
|
PWCHAR pwszQosObject;
|
|
DWORD dwNumArg;
|
|
DWORD dwErr;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
if (dwNumArg != 1)
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
//
|
|
// Get name of the qosobject to delete
|
|
//
|
|
|
|
pwszQosObject = pptcArguments[dwCurrentIndex];
|
|
|
|
return GetQosAddDelQosObject(pwszQosObject, NULL, FALSE);
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleQosShowQosObject(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for showing qos objects
|
|
in the global info.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,FALSE,FALSE},
|
|
{TOKEN_OPT_QOSOBJECT_TYPE,FALSE,FALSE}};
|
|
PTCHAR pszQosObject;
|
|
ULONG dwObjectType;
|
|
DWORD dwNumOpt, dwRes;
|
|
DWORD dwNumArg, i, j;
|
|
DWORD dwTagType, dwErr;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
// Init type to indicate a "generic" object
|
|
dwObjectType = QOS_OBJECT_END_OF_LIST;
|
|
|
|
pszQosObject = NULL;
|
|
|
|
if (dwCurrentIndex < dwArgCount)
|
|
{
|
|
//
|
|
// Get name of the qosobject to show
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
for (i = 0; i < dwNumArg; i++)
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0 :
|
|
// QOS OBJECT NAME
|
|
pszQosObject = pptcArguments[i + dwCurrentIndex];
|
|
break;
|
|
|
|
case 1 :
|
|
{
|
|
// QOS OBJECT TYPE
|
|
|
|
TOKEN_VALUE rgEnums[] =
|
|
{{TOKEN_OPT_QOSOBJECT_DIFFSERV, QOS_OBJECT_DIFFSERV},
|
|
{TOKEN_OPT_QOSOBJECT_SD_MODE, QOS_OBJECT_SD_MODE}};
|
|
|
|
GET_ENUM_TAG_VALUE();
|
|
|
|
dwObjectType = dwRes;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
}
|
|
|
|
return ShowQosObjects(NULL, pszQosObject, dwObjectType);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosShowGenericQosObject(
|
|
DWORD dwQosObjectType,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for showing qos objects
|
|
in the global info.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,FALSE,FALSE}};
|
|
PTCHAR pszQosObject;
|
|
DWORD dwNumArg;
|
|
DWORD dwTagType, dwErr;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
pszQosObject = NULL;
|
|
|
|
if (dwCurrentIndex < dwArgCount)
|
|
{
|
|
//
|
|
// Get name of the qosobject to show
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
if (dwNumArg != 1)
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
pszQosObject = pptcArguments[dwCurrentIndex];
|
|
}
|
|
|
|
return ShowQosObjects(NULL, pszQosObject, dwQosObjectType);
|
|
}
|
|
|
|
//
|
|
// SDMode Add, Del, Show Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosAddSdMode(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for adding shape modes
|
|
to the global info.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_SHAPING_MODE,TRUE,FALSE}};
|
|
QOS_SD_MODE qsdMode;
|
|
PTCHAR pszSdMode;
|
|
DWORD dwSdMode, dwNumArg, i, j, dwErr, dwRes;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
// Init to -1 to indicate value not filled in
|
|
dwSdMode = -1;
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
//
|
|
// Process the arguments now
|
|
//
|
|
|
|
for (i = 0; i < dwNumArg; i++)
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0 :
|
|
// SDMODE_NAME
|
|
pszSdMode = pptcArguments[i + dwCurrentIndex];
|
|
break;
|
|
|
|
case 1:
|
|
{
|
|
// SHAPING
|
|
TOKEN_VALUE rgEnums[] =
|
|
{{TOKEN_OPT_SDMODE_BORROW, TC_NONCONF_BORROW},
|
|
{TOKEN_OPT_SDMODE_SHAPE, TC_NONCONF_SHAPE},
|
|
{TOKEN_OPT_SDMODE_DISCARD, TC_NONCONF_DISCARD},
|
|
{TOKEN_OPT_SDMODE_BORROW_PLUS, TC_NONCONF_BORROW_PLUS}};
|
|
|
|
GET_ENUM_TAG_VALUE();
|
|
|
|
dwSdMode = dwRes;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
#if 0
|
|
// interface name should be present
|
|
// and also the shaping mode value
|
|
|
|
if ((!pttTags[0].bPresent) ||
|
|
(!pttTags[1].bPresent))
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
#endif
|
|
// Create a new QOS object with inp
|
|
qsdMode.ObjectHdr.ObjectType = QOS_OBJECT_SD_MODE ;
|
|
qsdMode.ObjectHdr.ObjectLength = sizeof(QOS_SD_MODE);
|
|
qsdMode.ShapeDiscardMode = dwSdMode;
|
|
|
|
dwErr = GetQosAddDelQosObject(pszSdMode,
|
|
(QOS_OBJECT_HDR *)&qsdMode,
|
|
TRUE);
|
|
}
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleQosShowSdMode(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for showing shape modes
|
|
in the global info.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return HandleQosShowGenericQosObject(QOS_OBJECT_SD_MODE,
|
|
pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
pbDone);
|
|
}
|
|
|
|
//
|
|
// QosObjectOnFlow Add, Del Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosAddQosObjectOnIfFlow(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return GetQosAddDelQosObjectOnFlowOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
TRUE);
|
|
}
|
|
|
|
DWORD
|
|
HandleQosDelQosObjectOnIfFlow(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return GetQosAddDelQosObjectOnFlowOpt(pptcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
FALSE);
|
|
}
|
|
|
|
//
|
|
// Filter Add, Del, Set Handlers
|
|
//
|
|
|
|
DWORD
|
|
HandleQosAttachFilterToFlow(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD
|
|
HandleQosDetachFilterFromFlow(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD
|
|
HandleQosModifyFilterOnFlow(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
DWORD
|
|
HandleQosShowFilterOnFlow(
|
|
PWCHAR pwszMachine,
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
MIB_SERVER_HANDLE hMibServer,
|
|
BOOL *pbDone
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
return ERROR_NOT_SUPPORTED;
|
|
}
|
|
|
|
//
|
|
// If Helper functions
|
|
//
|
|
|
|
DWORD
|
|
GetQosSetIfOpt(
|
|
IN PTCHAR *pptcArguments,
|
|
IN DWORD dwCurrentIndex,
|
|
IN DWORD dwArgCount,
|
|
IN PWCHAR wszIfName,
|
|
IN DWORD dwSizeOfwszIfName,
|
|
OUT PIPQOS_IF_CONFIG pChangeCfg,
|
|
OUT DWORD *pdwBitVector,
|
|
IN BOOL bAddSet
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
Gets options for set interface, add interface
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
wszIfName - Interface name.
|
|
dwSizeOfwszIfName-Size of the wszIfName buffer
|
|
pChangeCfg - The config containing changes values
|
|
pdwBitVector - Bit vector specifying what values have changed
|
|
bAddSet - Called when If entry is being created or set
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr = NO_ERROR,dwRes;
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_IF_STATE,FALSE,FALSE}};
|
|
DWORD dwNumOpt;
|
|
DWORD dwNumArg, i, j;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
for ( i = 0; i < dwNumArg; i++)
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0 :
|
|
{
|
|
//
|
|
// INTERFACE_NAME
|
|
//
|
|
|
|
IpmontrGetIfNameFromFriendlyName(pptcArguments[i + dwCurrentIndex],
|
|
wszIfName,&dwSizeOfwszIfName);
|
|
|
|
break;
|
|
}
|
|
|
|
case 1:
|
|
{
|
|
//
|
|
// STATE
|
|
//
|
|
|
|
TOKEN_VALUE rgEnums[] =
|
|
{{TOKEN_OPT_VALUE_DISABLE, IPQOS_STATE_DISABLED},
|
|
{TOKEN_OPT_VALUE_ENABLE, IPQOS_STATE_ENABLED}};
|
|
|
|
GET_ENUM_TAG_VALUE();
|
|
|
|
pChangeCfg->QosState = dwRes;
|
|
|
|
*pdwBitVector |= QOS_IF_STATE_MASK;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
|
|
// interface name should be present
|
|
|
|
if (!pttTags[0].bPresent)
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
#endif
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//
|
|
// Flow Helper functions
|
|
//
|
|
|
|
DWORD
|
|
GetQosAddDelIfFlowOpt(
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
BOOL bAdd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for add/del/set(modify) flows
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
bAdd - Adding or deleting flows
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
PIPQOS_IF_CONFIG piicSrc = NULL, piicDst = NULL;
|
|
DWORD dwBlkSize, dwNewBlkSize, dwQosCount;
|
|
DWORD i, j, dwErr = NO_ERROR, dwNumOpt;
|
|
DWORD dwSkip, dwOffset, dwSize, dwBitVector = 0;
|
|
DWORD dwIfType;
|
|
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
|
|
DWORD dwBufferSize = sizeof(wszIfName);
|
|
PIPQOS_IF_FLOW pNextFlow, pDestFlow;
|
|
PWCHAR pwszFlowName;
|
|
DWORD dwNumArg;
|
|
PUCHAR pFlow;
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_FLOW_NAME,TRUE,FALSE}};
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
for ( i = 0; i < dwNumArg; i++ )
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0:
|
|
/* Get interface name for the flow */
|
|
IpmontrGetIfNameFromFriendlyName(pptcArguments[i + dwCurrentIndex],
|
|
wszIfName, &dwBufferSize);
|
|
break;
|
|
|
|
case 1:
|
|
/* Get the flow name for the flow */
|
|
pwszFlowName = pptcArguments[i + dwCurrentIndex];
|
|
break;
|
|
|
|
default:
|
|
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#if 0
|
|
// interface and flow names should be present
|
|
|
|
if ((!pttTags[0].bPresent) || (!pttTags[1].bPresent))
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Get the interface info and check if flow already exists
|
|
//
|
|
|
|
dwErr = IpmontrGetInfoBlockFromInterfaceInfo(wszIfName,
|
|
MS_IP_QOSMGR,
|
|
(PBYTE *) &piicSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount,
|
|
&dwIfType);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( piicSrc == NULL )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
pNextFlow = (PIPQOS_IF_FLOW)((PUCHAR)piicSrc + sizeof(IPQOS_IF_CONFIG));
|
|
|
|
for (j = 0; j < piicSrc->NumFlows; j++)
|
|
{
|
|
if (!_wcsicmp(pNextFlow->FlowName, pwszFlowName))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextFlow = (PIPQOS_IF_FLOW)
|
|
((PUCHAR) pNextFlow + pNextFlow->FlowSize);
|
|
}
|
|
|
|
if (bAdd)
|
|
{
|
|
if (j < piicSrc->NumFlows)
|
|
{
|
|
//
|
|
// We already have a flow by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOW_ALREADY_EXISTS,
|
|
pwszFlowName);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (j == piicSrc->NumFlows)
|
|
{
|
|
//
|
|
// We do not have a flow by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOW_NOT_FOUND,
|
|
pwszFlowName);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
// Flow was found at 'pNextFlow' position
|
|
}
|
|
|
|
if (bAdd)
|
|
{
|
|
//
|
|
// We have a new flow definition - update config
|
|
//
|
|
|
|
dwNewBlkSize = dwBlkSize + sizeof(IPQOS_IF_FLOW);
|
|
|
|
piicDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!piicDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
// Copy all the existing flows to the new config
|
|
memcpy(piicDst, piicSrc, dwBlkSize);
|
|
|
|
//
|
|
// Stick the new flow as the last flow in array
|
|
//
|
|
|
|
pDestFlow = (PIPQOS_IF_FLOW)((PUCHAR) piicDst + dwBlkSize);
|
|
|
|
wcscpy(pDestFlow->FlowName, pwszFlowName);
|
|
|
|
pDestFlow->FlowSize = sizeof(IPQOS_IF_FLOW);
|
|
|
|
pDestFlow->FlowDesc.SendingFlowspecName[0] = L'\0';
|
|
pDestFlow->FlowDesc.RecvingFlowspecName[0] = L'\0';
|
|
pDestFlow->FlowDesc.NumTcObjects = 0;
|
|
|
|
piicDst->NumFlows++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We have to del old flowspec defn - update config
|
|
//
|
|
|
|
dwNewBlkSize = dwBlkSize - pNextFlow->FlowSize;
|
|
|
|
piicDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!piicDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
dwOffset = (PUCHAR)pNextFlow - (PUCHAR)piicSrc;
|
|
|
|
// Copy the all the flowspecs that occur before
|
|
memcpy(piicDst, piicSrc, dwOffset);
|
|
|
|
// Copy the rest of the flowspecs as they are
|
|
dwSkip = dwOffset + pNextFlow->FlowSize;
|
|
memcpy((PUCHAR) piicDst + dwOffset,
|
|
(PUCHAR) piicSrc + dwSkip,
|
|
dwBlkSize - dwSkip);
|
|
|
|
piicDst->NumFlows--;
|
|
}
|
|
|
|
// Update the interface config by setting new info
|
|
|
|
dwErr = IpmontrSetInfoBlockInInterfaceInfo(wszIfName,
|
|
MS_IP_QOSMGR,
|
|
(PBYTE) piicDst,
|
|
dwNewBlkSize,
|
|
dwQosCount);
|
|
}
|
|
while (FALSE);
|
|
|
|
HEAP_FREE_NOT_NULL(piicSrc);
|
|
HEAP_FREE_NOT_NULL(piicDst);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
DWORD
|
|
ShowQosFlows(
|
|
IN HANDLE hFile,
|
|
IN PWCHAR pwszIfGuid,
|
|
IN PWCHAR wszFlowName
|
|
)
|
|
{
|
|
PMPR_INTERFACE_0 pmi0;
|
|
DWORD dwErr, dwCount, dwTotal, i;
|
|
|
|
if (pwszIfGuid)
|
|
{
|
|
return ShowQosFlowsOnIf(hFile, pwszIfGuid, wszFlowName);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Enumerate all interfaces applicable to QOS
|
|
//
|
|
|
|
dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0,
|
|
&dwCount,
|
|
&dwTotal);
|
|
|
|
if(dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
for(i = 0; i < dwCount; i++)
|
|
{
|
|
ShowQosFlowsOnIf(hFile,
|
|
pmi0[i].wszInterfaceName,
|
|
wszFlowName);
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
ShowQosFlowsOnIf(
|
|
IN HANDLE hFile,
|
|
IN PWCHAR pwszIfGuid,
|
|
IN PWCHAR wszFlowName
|
|
)
|
|
{
|
|
WCHAR wszInterfaceName[ MAX_INTERFACE_NAME_LEN + 1 ] = L"\0";
|
|
DWORD dwBufferSize = sizeof(wszInterfaceName);
|
|
PWCHAR pwszFriendlyIfName = NULL;
|
|
|
|
PIPQOS_IF_CONFIG piicSrc;
|
|
DWORD dwBlkSize,dwQosCount;
|
|
DWORD dwIfType, dwErr, j, k;
|
|
PIPQOS_IF_FLOW pNextFlow;
|
|
PWCHAR pwszFlowName = NULL;
|
|
PWCHAR pwszNextObject, pwszObjectName = NULL;
|
|
PWCHAR pwszSendingFlowspec, pwszRecvingFlowspec;
|
|
|
|
dwErr = IpmontrGetInfoBlockFromInterfaceInfo(pwszIfGuid,
|
|
MS_IP_QOSMGR,
|
|
(PBYTE *) &piicSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount,
|
|
&dwIfType);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
if ( piicSrc == NULL )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Get friendly name for interface
|
|
//
|
|
|
|
dwErr = IpmontrGetFriendlyNameFromIfName(pwszIfGuid,
|
|
wszInterfaceName,
|
|
&dwBufferSize);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
pwszFriendlyIfName = MakeQuotedString( wszInterfaceName );
|
|
|
|
if ( pwszFriendlyIfName == NULL )
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
pNextFlow = (PIPQOS_IF_FLOW)((PUCHAR)piicSrc + sizeof(IPQOS_IF_CONFIG));
|
|
|
|
for (j = 0; j < piicSrc->NumFlows; j++)
|
|
{
|
|
if ((!wszFlowName) ||
|
|
(!_wcsicmp(pNextFlow->FlowName, wszFlowName)))
|
|
{
|
|
//
|
|
// Print or dump the flow now
|
|
//
|
|
|
|
pwszFlowName = MakeQuotedString(pNextFlow->FlowName);
|
|
|
|
if (pwszFlowName == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
// Print or dump flowspecs
|
|
|
|
pwszSendingFlowspec =
|
|
MakeQuotedString(pNextFlow->FlowDesc.SendingFlowspecName);
|
|
|
|
pwszRecvingFlowspec =
|
|
MakeQuotedString(pNextFlow->FlowDesc.RecvingFlowspecName);
|
|
|
|
if (hFile)
|
|
{
|
|
DisplayMessageT(DMP_QOS_DELETE_FLOW,
|
|
pwszFriendlyIfName,
|
|
pwszFlowName);
|
|
|
|
|
|
DisplayMessageT(DMP_QOS_ADD_FLOW,
|
|
pwszFriendlyIfName,
|
|
pwszFlowName);
|
|
|
|
if (!_wcsicmp(pwszSendingFlowspec, pwszRecvingFlowspec))
|
|
{
|
|
if (pNextFlow->FlowDesc.SendingFlowspecName[0])
|
|
{
|
|
DisplayMessageT(DMP_QOS_ADD_FLOWSPEC_ON_FLOW_BI,
|
|
pwszFriendlyIfName,
|
|
pwszFlowName,
|
|
pwszSendingFlowspec);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pNextFlow->FlowDesc.RecvingFlowspecName[0])
|
|
{
|
|
DisplayMessageT(DMP_QOS_ADD_FLOWSPEC_ON_FLOW_IN,
|
|
pwszFriendlyIfName,
|
|
pwszFlowName,
|
|
pwszRecvingFlowspec);
|
|
}
|
|
|
|
if (pNextFlow->FlowDesc.SendingFlowspecName[0])
|
|
{
|
|
DisplayMessageT(DMP_QOS_ADD_FLOWSPEC_ON_FLOW_OUT,
|
|
pwszFriendlyIfName,
|
|
pwszFlowName,
|
|
pwszSendingFlowspec);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(g_hModule, MSG_QOS_FLOW_INFO,
|
|
pwszFlowName,
|
|
pwszFriendlyIfName,
|
|
pwszRecvingFlowspec,
|
|
pwszSendingFlowspec,
|
|
pNextFlow->FlowDesc.NumTcObjects);
|
|
}
|
|
|
|
// Print or dump qos objects
|
|
|
|
pwszNextObject =
|
|
(PWCHAR) ((PUCHAR) pNextFlow + sizeof(IPQOS_IF_FLOW));
|
|
|
|
for (k = 0; k < pNextFlow->FlowDesc.NumTcObjects; k++)
|
|
{
|
|
pwszObjectName = MakeQuotedString(pwszNextObject);
|
|
|
|
if ( pwszObjectName == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if (hFile)
|
|
{
|
|
DisplayMessageT(DMP_QOS_ADD_QOSOBJECT_ON_FLOW,
|
|
pwszFriendlyIfName,
|
|
pwszFlowName,
|
|
pwszObjectName);
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(g_hModule, MSG_QOS_QOSOBJECT_INFO,
|
|
k,
|
|
pwszObjectName);
|
|
}
|
|
|
|
pwszNextObject += MAX_STRING_LENGTH;
|
|
|
|
FreeQuotedString(pwszObjectName);
|
|
}
|
|
|
|
if ( pwszFlowName )
|
|
{
|
|
FreeQuotedString( pwszFlowName );
|
|
pwszFlowName = NULL;
|
|
}
|
|
|
|
//
|
|
// If we matched flow, then done
|
|
//
|
|
|
|
if ((wszFlowName) || (dwErr != NO_ERROR))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
pNextFlow = (PIPQOS_IF_FLOW)
|
|
((PUCHAR) pNextFlow + pNextFlow->FlowSize);
|
|
}
|
|
|
|
if ( pwszFriendlyIfName )
|
|
{
|
|
FreeQuotedString( pwszFriendlyIfName );
|
|
}
|
|
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
if ((wszFlowName) && (j == piicSrc->NumFlows))
|
|
{
|
|
// We didnt find the flow we are looking for
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOW_NOT_FOUND,
|
|
wszFlowName);
|
|
return ERROR_SUPPRESS_OUTPUT;
|
|
}
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
//
|
|
// DsRule, DsMap Helpers
|
|
//
|
|
|
|
DWORD
|
|
GetQosAddDelDsRuleOpt(
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
BOOL bAdd
|
|
)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
TAG_TYPE pttTags[] = {
|
|
{TOKEN_OPT_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_INBOUND_DS_FIELD,TRUE,FALSE},
|
|
{TOKEN_OPT_CONF_OUTBOUND_DS_FIELD,FALSE,FALSE},
|
|
{TOKEN_OPT_NONCONF_OUTBOUND_DS_FIELD,FALSE,FALSE},
|
|
{TOKEN_OPT_CONF_USER_PRIORITY,FALSE,FALSE},
|
|
{TOKEN_OPT_NONCONF_USER_PRIORITY,FALSE,FALSE}};
|
|
PIPQOS_NAMED_QOSOBJECT pThisQosObject, pNextQosObject;
|
|
PVOID pBuffer;
|
|
PTCHAR pszDsMap;
|
|
QOS_DIFFSERV *pDsMap;
|
|
QOS_DIFFSERV_RULE dsRule, *pDsRule, *pNextDsRule;
|
|
PIPQOS_GLOBAL_CONFIG pigcSrc = NULL, pigcDst = NULL;
|
|
DWORD dwBlkSize, dwNewBlkSize, dwQosCount;
|
|
DWORD dwNumOpt, dwRes;
|
|
DWORD dwNumArg, i, j;
|
|
DWORD dwSkip, dwOffset;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
//
|
|
// We need all params for add and atleast
|
|
// the dsmap name n dsrule num for delete
|
|
//
|
|
|
|
if (( bAdd && (dwNumArg != 6)) ||
|
|
(!bAdd && (dwNumArg != 2)))
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
pDsRule = &dsRule;
|
|
|
|
//
|
|
// Initialize the diffserv rule definition
|
|
//
|
|
|
|
memset(pDsRule, 0, sizeof(QOS_DIFFSERV_RULE));
|
|
|
|
//
|
|
// Process the arguments now
|
|
//
|
|
|
|
for ( i = 0; i < dwNumArg; i++)
|
|
{
|
|
// All params except the first are uchar vals
|
|
|
|
if ( pdwTagType[i] > 0)
|
|
{
|
|
// What if this is not a valid ULONG ? '0' will not do...
|
|
dwRes = _tcstoul(pptcArguments[i + dwCurrentIndex],NULL,10);
|
|
}
|
|
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0:
|
|
|
|
//
|
|
// DSMAP Name: See if we already have the name
|
|
//
|
|
|
|
pszDsMap = pptcArguments[i + dwCurrentIndex];
|
|
|
|
dwErr = IpmontrGetInfoBlockFromGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE *) &pigcSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( pigcSrc == NULL )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
dwOffset = FIELD_OFFSET(IPQOS_NAMED_QOSOBJECT, QosObjectHdr);
|
|
|
|
pThisQosObject = NULL;
|
|
|
|
pNextQosObject =
|
|
(PIPQOS_NAMED_QOSOBJECT)((PUCHAR) pigcSrc
|
|
+ sizeof(IPQOS_GLOBAL_CONFIG)
|
|
+ (pigcSrc->NumFlowspecs *
|
|
sizeof(IPQOS_NAMED_FLOWSPEC)));
|
|
|
|
for (j = 0; j < pigcSrc->NumQosObjects; j++)
|
|
{
|
|
if (!_wcsicmp(pNextQosObject->QosObjectName,
|
|
pszDsMap))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextQosObject =
|
|
(PIPQOS_NAMED_QOSOBJECT)
|
|
((PUCHAR) pNextQosObject +
|
|
dwOffset +
|
|
pNextQosObject->QosObjectHdr.ObjectLength);
|
|
}
|
|
|
|
if (j < pigcSrc->NumQosObjects)
|
|
{
|
|
//
|
|
// You cannot add/del dsrules from a non dsmap
|
|
//
|
|
|
|
if (pNextQosObject->QosObjectHdr.ObjectType !=
|
|
QOS_OBJECT_DIFFSERV)
|
|
{
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_FUNCTION;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (bAdd)
|
|
{
|
|
if (j < pigcSrc->NumQosObjects)
|
|
{
|
|
// Remember QOS object you are interested in
|
|
pThisQosObject = pNextQosObject;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (j == pigcSrc->NumQosObjects)
|
|
{
|
|
//
|
|
// We do not have a qos object by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_QOSOBJECT_NOT_FOUND,
|
|
pszDsMap);
|
|
i = dwNumArg;
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
// Remember QOS object you are interested in
|
|
pThisQosObject = pNextQosObject;
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
// INBOUND_DS
|
|
pDsRule->InboundDSField = (UCHAR) dwRes;
|
|
break;
|
|
|
|
case 2:
|
|
// CONF_OUTBOUND_DS
|
|
pDsRule->ConformingOutboundDSField = (UCHAR) dwRes;
|
|
break;
|
|
|
|
case 3:
|
|
// NONCONF_OUTBOUND_DS
|
|
pDsRule->NonConformingOutboundDSField = (UCHAR) dwRes;
|
|
break;
|
|
|
|
case 4:
|
|
// CONF_USER_PRIOTITY
|
|
pDsRule->ConformingUserPriority = (UCHAR) dwRes;
|
|
break;
|
|
|
|
case 5:
|
|
// NONCONF_USER_PRIOTITY
|
|
pDsRule->NonConformingUserPriority = (UCHAR) dwRes;
|
|
break;
|
|
|
|
default:
|
|
{
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// interface name should be present
|
|
// and the ds rule id (inbound ds)
|
|
//
|
|
|
|
if ((!pttTags[0].bPresent) ||
|
|
(!pttTags[1].bPresent))
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// and the test of the info for add
|
|
//
|
|
|
|
if (bAdd)
|
|
{
|
|
if ((!pttTags[2].bPresent) ||
|
|
(!pttTags[3].bPresent) ||
|
|
(!pttTags[4].bPresent) ||
|
|
(!pttTags[5].bPresent))
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if 1
|
|
//
|
|
// BUGBUG: Adding and deleting DS rules will cause
|
|
// the corresponding map to be updated, but will
|
|
// this result in getting dependent flows changed?
|
|
//
|
|
#endif
|
|
|
|
if (bAdd)
|
|
{
|
|
if (pThisQosObject)
|
|
{
|
|
//
|
|
// Check if this dsrule is already present
|
|
//
|
|
|
|
pDsMap = (QOS_DIFFSERV *) &pThisQosObject->QosObjectHdr;
|
|
|
|
pNextDsRule = (QOS_DIFFSERV_RULE *)&pDsMap->DiffservRule[0];
|
|
|
|
for (j = 0; j < pDsMap->DSFieldCount; j++)
|
|
{
|
|
if (pNextDsRule->InboundDSField ==
|
|
pDsRule->InboundDSField)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextDsRule++;
|
|
}
|
|
|
|
dwOffset = (PUCHAR)pNextDsRule - (PUCHAR)pigcSrc;
|
|
|
|
if (j < pDsMap->DSFieldCount)
|
|
{
|
|
//
|
|
// Update existing DS rule with info
|
|
//
|
|
|
|
*pNextDsRule = *pDsRule;
|
|
|
|
dwSkip = 0;
|
|
|
|
pBuffer = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Initialize new DS rule for new rule info
|
|
//
|
|
|
|
dwSkip = sizeof(QOS_DIFFSERV_RULE);
|
|
|
|
pNextDsRule = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
dwSkip);
|
|
|
|
if (pNextDsRule == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
*pNextDsRule = *pDsRule;
|
|
|
|
//
|
|
// Update num of dfsrv rules in src buff
|
|
// so that dst copy results in new value
|
|
//
|
|
|
|
pDsMap->DSFieldCount++;
|
|
|
|
pDsMap->ObjectHdr.ObjectLength +=sizeof(QOS_DIFFSERV_RULE);
|
|
|
|
pBuffer = pNextDsRule;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Initialize a new DS map to hold the rule
|
|
//
|
|
|
|
dwSkip = sizeof(IPQOS_NAMED_QOSOBJECT) +
|
|
sizeof(ULONG) + // this for DSFieldCount
|
|
sizeof(QOS_DIFFSERV_RULE);
|
|
|
|
dwOffset = (PUCHAR) pNextQosObject - (PUCHAR) pigcSrc;
|
|
|
|
pThisQosObject = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
dwSkip);
|
|
|
|
if (pThisQosObject == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
wcscpy(pThisQosObject->QosObjectName, pszDsMap);
|
|
|
|
pDsMap = (QOS_DIFFSERV *) &pThisQosObject->QosObjectHdr;
|
|
|
|
pDsMap->ObjectHdr.ObjectType = QOS_OBJECT_DIFFSERV;
|
|
pDsMap->ObjectHdr.ObjectLength =
|
|
dwSkip - FIELD_OFFSET(IPQOS_NAMED_QOSOBJECT, QosObjectHdr);
|
|
|
|
pDsMap->DSFieldCount = 1;
|
|
|
|
pNextDsRule =
|
|
(QOS_DIFFSERV_RULE *) &pDsMap->DiffservRule[0];
|
|
|
|
*pNextDsRule = *pDsRule;
|
|
|
|
//
|
|
// Update num of qos objects in src buff
|
|
// so that dst copy results in new value
|
|
//
|
|
|
|
pigcSrc->NumQosObjects++;
|
|
|
|
pBuffer = pThisQosObject;
|
|
}
|
|
|
|
dwNewBlkSize = dwBlkSize + dwSkip;
|
|
|
|
pigcDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!pigcDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
// Copy the all the info that occurs before
|
|
memcpy(pigcDst, pigcSrc, dwOffset);
|
|
|
|
// Copy the new information after dwOffset
|
|
memcpy((PUCHAR) pigcDst + dwOffset,
|
|
pBuffer,
|
|
dwSkip);
|
|
|
|
// Copy the rest of the info as it is
|
|
memcpy((PUCHAR) pigcDst + dwOffset + dwSkip,
|
|
(PUCHAR) pigcSrc + dwOffset,
|
|
dwBlkSize - dwOffset);
|
|
|
|
HEAP_FREE_NOT_NULL(pBuffer);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Check if this dsrule is already present
|
|
//
|
|
|
|
pDsMap = (QOS_DIFFSERV *) &pThisQosObject->QosObjectHdr;
|
|
|
|
pNextDsRule = (QOS_DIFFSERV_RULE *)&pDsMap->DiffservRule[0];
|
|
|
|
for (j = 0; j < pDsMap->DSFieldCount; j++)
|
|
{
|
|
if (pNextDsRule->InboundDSField ==
|
|
pDsRule->InboundDSField)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextDsRule++;
|
|
}
|
|
|
|
if (j == pDsMap->DSFieldCount)
|
|
{
|
|
// Did not find DS rule in the DS map
|
|
DisplayMessage(g_hModule,
|
|
MSG_DSRULE_NOT_FOUND,
|
|
pszDsMap,
|
|
pDsRule->InboundDSField);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
if (pDsMap->DSFieldCount == 1)
|
|
{
|
|
// Last DS rule in the DS map
|
|
|
|
dwOffset = (PUCHAR)pThisQosObject - (PUCHAR)pigcSrc;
|
|
|
|
dwSkip = sizeof(IPQOS_NAMED_QOSOBJECT) +
|
|
sizeof(ULONG) + // this for DSFieldCount
|
|
sizeof(QOS_DIFFSERV_RULE);
|
|
|
|
//
|
|
// Update num of qos objects in src buff
|
|
// so that dst copy results in new value
|
|
//
|
|
|
|
pigcSrc->NumQosObjects--;
|
|
}
|
|
else
|
|
{
|
|
// More than 1 rule in DS map
|
|
|
|
dwOffset = (PUCHAR)pNextDsRule - (PUCHAR)pigcSrc;
|
|
|
|
dwSkip = sizeof(QOS_DIFFSERV_RULE);
|
|
|
|
//
|
|
// Update num of dfsrv rules in src buff
|
|
// so that dst copy results in new value
|
|
//
|
|
|
|
pDsMap->DSFieldCount--;
|
|
|
|
pDsMap->ObjectHdr.ObjectLength -= sizeof(QOS_DIFFSERV_RULE);
|
|
}
|
|
|
|
dwNewBlkSize = dwBlkSize - dwSkip;
|
|
|
|
pigcDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!pigcDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
// Copy the all the info that occurs before
|
|
memcpy(pigcDst, pigcSrc, dwOffset);
|
|
|
|
// Copy the rest of the info as it is
|
|
dwOffset += dwSkip;
|
|
memcpy((PUCHAR) pigcDst + dwOffset - dwSkip,
|
|
(PUCHAR) pigcSrc + dwOffset,
|
|
dwBlkSize - dwOffset);
|
|
}
|
|
|
|
// Update the global config by setting new info
|
|
|
|
dwErr = IpmontrSetInfoBlockInGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE) pigcDst,
|
|
dwNewBlkSize,
|
|
dwQosCount);
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
UpdateAllInterfaceConfigs();
|
|
}
|
|
}
|
|
while (FALSE);
|
|
|
|
HEAP_FREE_NOT_NULL(pigcSrc);
|
|
HEAP_FREE_NOT_NULL(pigcDst);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
DWORD
|
|
ShowQosDsMap(
|
|
IN HANDLE hFile,
|
|
IN PWCHAR wszDsMapName,
|
|
IN QOS_OBJECT_HDR *pQosObject
|
|
)
|
|
{
|
|
QOS_DIFFSERV_RULE *pDsRule;
|
|
QOS_DIFFSERV *pDsMap;
|
|
PWCHAR pwszDsMapName;
|
|
DWORD dwErr, k;
|
|
|
|
pDsMap = (QOS_DIFFSERV *) pQosObject;
|
|
|
|
//
|
|
// Print or dump the dsmap now
|
|
//
|
|
|
|
do
|
|
{
|
|
pwszDsMapName = MakeQuotedString(wszDsMapName);
|
|
|
|
if (pwszDsMapName == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if (hFile)
|
|
{
|
|
DisplayMessageT(DMP_QOS_DSMAP_HEADER);
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(g_hModule, MSG_QOS_DSMAP_INFO,
|
|
pwszDsMapName,
|
|
pDsMap->DSFieldCount);
|
|
}
|
|
|
|
//
|
|
// Print each DS rule in the map
|
|
//
|
|
|
|
pDsRule = (QOS_DIFFSERV_RULE *) &pDsMap->DiffservRule[0];
|
|
|
|
for (k = 0; k < pDsMap->DSFieldCount; k++)
|
|
{
|
|
if (hFile)
|
|
{
|
|
DisplayMessageT(DMP_QOS_DELETE_DSRULE,
|
|
pwszDsMapName,
|
|
pDsRule->InboundDSField);
|
|
|
|
DisplayMessageT(DMP_QOS_ADD_DSRULE,
|
|
pwszDsMapName,
|
|
pDsRule->InboundDSField,
|
|
pDsRule->ConformingOutboundDSField,
|
|
pDsRule->NonConformingOutboundDSField,
|
|
pDsRule->ConformingUserPriority,
|
|
pDsRule->NonConformingUserPriority);
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(g_hModule, MSG_QOS_DSRULE_INFO,
|
|
pwszDsMapName,
|
|
k,
|
|
pDsRule->InboundDSField,
|
|
pDsRule->ConformingOutboundDSField,
|
|
pDsRule->NonConformingOutboundDSField,
|
|
pDsRule->ConformingUserPriority,
|
|
pDsRule->NonConformingUserPriority);
|
|
}
|
|
|
|
pDsRule++;
|
|
}
|
|
|
|
if (hFile)
|
|
{
|
|
DisplayMessageT(DMP_QOS_DSMAP_FOOTER);
|
|
}
|
|
|
|
if ( pwszDsMapName )
|
|
{
|
|
FreeQuotedString( pwszDsMapName );
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
while (FALSE);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// SD Mode Helpers
|
|
//
|
|
|
|
DWORD
|
|
ShowQosSdMode(
|
|
IN HANDLE hFile,
|
|
IN PWCHAR wszSdModeName,
|
|
IN QOS_OBJECT_HDR *pQosObject
|
|
)
|
|
{
|
|
QOS_SD_MODE *pSdMode;
|
|
PWCHAR pwszSdModeName;
|
|
DWORD dwErr, k;
|
|
PTCHAR ptszSdMode = NULL;
|
|
VALUE_TOKEN vtSdMode1[] =
|
|
{TC_NONCONF_BORROW,TOKEN_OPT_SDMODE_BORROW,
|
|
TC_NONCONF_SHAPE,TOKEN_OPT_SDMODE_SHAPE,
|
|
TC_NONCONF_DISCARD,TOKEN_OPT_SDMODE_DISCARD,
|
|
TC_NONCONF_BORROW_PLUS,TOKEN_OPT_SDMODE_BORROW_PLUS};
|
|
|
|
VALUE_STRING vtSdMode2[] =
|
|
{TC_NONCONF_BORROW,STRING_SDMODE_BORROW,
|
|
TC_NONCONF_SHAPE,STRING_SDMODE_SHAPE,
|
|
TC_NONCONF_DISCARD,STRING_SDMODE_DISCARD,
|
|
TC_NONCONF_BORROW_PLUS,STRING_SDMODE_BORROW_PLUS};
|
|
|
|
pSdMode = (QOS_SD_MODE *)pQosObject;
|
|
|
|
//
|
|
// Print or dump the sdmode now
|
|
//
|
|
|
|
do
|
|
{
|
|
pwszSdModeName = MakeQuotedString(wszSdModeName);
|
|
|
|
if (pwszSdModeName == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get service type of flowspec
|
|
//
|
|
|
|
GetAltDisplayString(g_hModule, hFile,
|
|
pSdMode->ShapeDiscardMode,
|
|
vtSdMode1,
|
|
vtSdMode2,
|
|
NUM_VALUES_IN_TABLE(vtSdMode1),
|
|
&ptszSdMode);
|
|
|
|
if ( ptszSdMode == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if (hFile)
|
|
{
|
|
DisplayMessageT(DMP_QOS_DEL_SDMODE,
|
|
pwszSdModeName);
|
|
|
|
DisplayMessageT(DMP_QOS_ADD_SDMODE,
|
|
pwszSdModeName,
|
|
ptszSdMode);
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(g_hModule, MSG_QOS_SDMODE_INFO,
|
|
pwszSdModeName,
|
|
ptszSdMode);
|
|
}
|
|
|
|
FREE_STRING_NOT_NULL ( ptszSdMode );
|
|
|
|
if ( pwszSdModeName )
|
|
{
|
|
FreeQuotedString( pwszSdModeName );
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
while (FALSE);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
//
|
|
// Qos Object Helpers
|
|
//
|
|
|
|
DWORD
|
|
GetQosAddDelQosObject(
|
|
IN PWCHAR pwszQosObjectName,
|
|
IN QOS_OBJECT_HDR *pQosObject,
|
|
IN BOOL bAdd
|
|
)
|
|
{
|
|
PIPQOS_NAMED_QOSOBJECT pNextQosObject;
|
|
PIPQOS_GLOBAL_CONFIG pigcSrc = NULL, pigcDst = NULL;
|
|
DWORD dwBlkSize, dwNewBlkSize, dwQosCount;
|
|
DWORD dwErr, dwSize, dwSkip, dwOffset, j;
|
|
|
|
dwErr = IpmontrGetInfoBlockFromGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE *) &pigcSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
if (pigcSrc == NULL)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
dwOffset = FIELD_OFFSET(IPQOS_NAMED_QOSOBJECT, QosObjectHdr);
|
|
|
|
//
|
|
// Search for a QOS Object with this name
|
|
//
|
|
|
|
pNextQosObject = (PIPQOS_NAMED_QOSOBJECT)((PUCHAR) pigcSrc
|
|
+ sizeof(IPQOS_GLOBAL_CONFIG)
|
|
+ (pigcSrc->NumFlowspecs *
|
|
sizeof(IPQOS_NAMED_FLOWSPEC)));
|
|
|
|
for (j = 0; j < pigcSrc->NumQosObjects; j++)
|
|
{
|
|
if (!_wcsicmp(pNextQosObject->QosObjectName,
|
|
pwszQosObjectName))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextQosObject = (PIPQOS_NAMED_QOSOBJECT)
|
|
((PUCHAR) pNextQosObject +
|
|
dwOffset +
|
|
pNextQosObject->QosObjectHdr.ObjectLength);
|
|
}
|
|
|
|
do
|
|
{
|
|
if (bAdd)
|
|
{
|
|
dwSize = FIELD_OFFSET(IPQOS_NAMED_QOSOBJECT, QosObjectHdr) +
|
|
pQosObject->ObjectLength;
|
|
dwSkip = 0;
|
|
|
|
if (j < pigcSrc->NumQosObjects)
|
|
{
|
|
//
|
|
// Do (not) allow overwriting qos objects
|
|
//
|
|
#if NO_UPDATE
|
|
//
|
|
// We already have a qos object by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_QOSOBJECT_ALREADY_EXISTS,
|
|
pwszQosObjectName);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
#endif
|
|
// Get the existing size of the qos object
|
|
dwSkip = FIELD_OFFSET(IPQOS_NAMED_QOSOBJECT, QosObjectHdr) +
|
|
pNextQosObject->QosObjectHdr.ObjectLength;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Update num of qos objects in src buff
|
|
// so that dst copy results in new value
|
|
//
|
|
|
|
pigcSrc->NumQosObjects++;
|
|
}
|
|
|
|
dwOffset = (PUCHAR) pNextQosObject - (PUCHAR) pigcSrc;
|
|
|
|
dwNewBlkSize = dwBlkSize + dwSize - dwSkip;
|
|
|
|
pigcDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!pigcDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
// Copy the all the info that occurs before
|
|
memcpy(pigcDst, pigcSrc, dwOffset);
|
|
|
|
// Copy the new information after dwOffset
|
|
|
|
// Copy the name of the qos object first
|
|
wcscpy((PWCHAR)((PUCHAR) pigcDst + dwOffset),
|
|
pwszQosObjectName);
|
|
|
|
// Copy the rest of the input information
|
|
memcpy((PUCHAR) pigcDst + dwOffset + MAX_WSTR_LENGTH,
|
|
(PUCHAR) pQosObject,
|
|
pQosObject->ObjectLength);
|
|
|
|
// Copy the rest of the info as it is
|
|
memcpy((PUCHAR) pigcDst + (dwOffset + dwSize),
|
|
(PUCHAR) pigcSrc + (dwOffset + dwSkip),
|
|
dwBlkSize - (dwOffset + dwSkip));
|
|
}
|
|
else
|
|
{
|
|
#if 1
|
|
//
|
|
// BUGBUG: What if there are dependent flows ?
|
|
//
|
|
#endif
|
|
if (j == pigcSrc->NumQosObjects)
|
|
{
|
|
//
|
|
// We do not have a qos object by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_QOSOBJECT_NOT_FOUND,
|
|
pwszQosObjectName);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Update num of qos objects in src buff
|
|
// so that dst copy results in new value
|
|
//
|
|
|
|
pigcSrc->NumQosObjects--;
|
|
|
|
dwOffset = (PUCHAR)pNextQosObject - (PUCHAR)pigcSrc;
|
|
|
|
dwSkip = FIELD_OFFSET(IPQOS_NAMED_QOSOBJECT, QosObjectHdr) +
|
|
pNextQosObject->QosObjectHdr.ObjectLength;
|
|
|
|
dwNewBlkSize = dwBlkSize - dwSkip;
|
|
|
|
pigcDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!pigcDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
// Copy the all the info that occurs before
|
|
memcpy(pigcDst, pigcSrc, dwOffset);
|
|
|
|
// Copy the rest of the info as it is
|
|
dwOffset += dwSkip;
|
|
memcpy((PUCHAR) pigcDst + dwOffset - dwSkip,
|
|
(PUCHAR) pigcSrc + dwOffset,
|
|
dwBlkSize - dwOffset);
|
|
}
|
|
|
|
// Update the global config by setting new info
|
|
|
|
dwErr = IpmontrSetInfoBlockInGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE) pigcDst,
|
|
dwNewBlkSize,
|
|
dwQosCount);
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
UpdateAllInterfaceConfigs();
|
|
}
|
|
}
|
|
while (FALSE);
|
|
|
|
HEAP_FREE_NOT_NULL(pigcSrc);
|
|
HEAP_FREE_NOT_NULL(pigcDst);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
DWORD
|
|
ShowQosObjects(
|
|
IN HANDLE hFile,
|
|
IN PWCHAR wszQosObjectName,
|
|
IN ULONG dwQosObjectType
|
|
)
|
|
{
|
|
PIPQOS_NAMED_QOSOBJECT pNextQosObject;
|
|
PIPQOS_GLOBAL_CONFIG pigcSrc;
|
|
PSHOW_QOS_OBJECT pfnShowQosObject;
|
|
DWORD dwBlkSize,dwQosCount;
|
|
DWORD dwOffset;
|
|
DWORD dwErr, j;
|
|
|
|
dwErr = IpmontrGetInfoBlockFromGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE *) &pigcSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
if ( pigcSrc == NULL )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
dwOffset = FIELD_OFFSET(IPQOS_NAMED_QOSOBJECT, QosObjectHdr);
|
|
|
|
pNextQosObject = (PIPQOS_NAMED_QOSOBJECT)((PUCHAR) pigcSrc
|
|
+ sizeof(IPQOS_GLOBAL_CONFIG)
|
|
+ (pigcSrc->NumFlowspecs *
|
|
sizeof(IPQOS_NAMED_FLOWSPEC)));
|
|
|
|
for (j = 0; j < pigcSrc->NumQosObjects; j++)
|
|
{
|
|
if ((dwQosObjectType == QOS_OBJECT_END_OF_LIST) ||
|
|
(dwQosObjectType == pNextQosObject->QosObjectHdr.ObjectType))
|
|
{
|
|
if ((!wszQosObjectName) ||
|
|
(!_wcsicmp(pNextQosObject->QosObjectName, wszQosObjectName)))
|
|
{
|
|
switch (pNextQosObject->QosObjectHdr.ObjectType)
|
|
{
|
|
case QOS_OBJECT_DIFFSERV:
|
|
pfnShowQosObject = ShowQosDsMap;
|
|
break;
|
|
|
|
case QOS_OBJECT_SD_MODE:
|
|
pfnShowQosObject = ShowQosSdMode;
|
|
break;
|
|
|
|
default:
|
|
pfnShowQosObject = ShowQosGenObj;
|
|
}
|
|
|
|
pfnShowQosObject(hFile,
|
|
pNextQosObject->QosObjectName,
|
|
&pNextQosObject->QosObjectHdr);
|
|
|
|
//
|
|
// If we matched the qos object name, then done
|
|
//
|
|
|
|
if (wszQosObjectName)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pNextQosObject = (PIPQOS_NAMED_QOSOBJECT)
|
|
((PUCHAR) pNextQosObject +
|
|
dwOffset +
|
|
pNextQosObject->QosObjectHdr.ObjectLength);
|
|
}
|
|
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
if ((wszQosObjectName) && (j == pigcSrc->NumQosObjects))
|
|
{
|
|
// We didnt find the qos object we are looking for
|
|
DisplayMessage(g_hModule,
|
|
MSG_QOSOBJECT_NOT_FOUND,
|
|
wszQosObjectName);
|
|
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
}
|
|
}
|
|
|
|
HEAP_FREE(pigcSrc);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
ShowQosGenObj(
|
|
IN HANDLE hFile,
|
|
IN PWCHAR wszGenObjName,
|
|
IN QOS_OBJECT_HDR *pQosObject
|
|
)
|
|
{
|
|
// We can print a general description from name and size
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
GetQosAddDelQosObjectOnFlowOpt(
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
BOOL bAdd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for attach and detach QOS objects
|
|
from flows.
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
bAdd - Adding or deleting flows
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
PIPQOS_GLOBAL_CONFIG pigcSrc = NULL;
|
|
PIPQOS_IF_CONFIG piicSrc = NULL, piicDst = NULL;
|
|
DWORD dwBlkSize, dwNewBlkSize, dwQosCount;
|
|
DWORD dwBlkSize1, dwQosCount1;
|
|
DWORD i, j, k, l;
|
|
DWORD dwErr = NO_ERROR, dwNumOpt;
|
|
DWORD dwRes;
|
|
DWORD dwSkip, dwOffset, dwSize, dwBitVector = 0;
|
|
DWORD dwIfType;
|
|
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
|
|
PIPQOS_NAMED_QOSOBJECT pNamedQosObject, pNextQosObject;
|
|
PIPQOS_IF_FLOW pNextFlow, pDestFlow;
|
|
PWCHAR pwszFlowName, pwszQosObject, pwszNextObject;
|
|
DWORD dwNumArg,
|
|
dwBufferSize = sizeof(wszIfName);
|
|
PUCHAR pFlow;
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_FLOW_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_QOSOBJECT,TRUE,FALSE}};
|
|
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
for ( i = 0; i < dwNumArg; i++ )
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0:
|
|
// INTERFACE NAME
|
|
IpmontrGetIfNameFromFriendlyName( pptcArguments[i + dwCurrentIndex],
|
|
wszIfName,&dwBufferSize);
|
|
break;
|
|
|
|
case 1:
|
|
// FLOW NAME
|
|
pwszFlowName = pptcArguments[i + dwCurrentIndex];
|
|
break;
|
|
|
|
case 2:
|
|
// QOSOBJECT NAME
|
|
pwszQosObject = pptcArguments[i + dwCurrentIndex];
|
|
break;
|
|
|
|
default:
|
|
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#if 0
|
|
// interface, flow, qosobject names should be present
|
|
|
|
if ((!pttTags[0].bPresent) ||
|
|
(!pttTags[1].bPresent) ||
|
|
(!pttTags[2].bPresent))
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Get the interface info and check if flow already exists
|
|
//
|
|
|
|
dwErr = IpmontrGetInfoBlockFromInterfaceInfo(wszIfName,
|
|
MS_IP_QOSMGR,
|
|
(PBYTE *) &piicSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount,
|
|
&dwIfType);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( piicSrc == NULL )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
pNextFlow = (PIPQOS_IF_FLOW)((PUCHAR)piicSrc + sizeof(IPQOS_IF_CONFIG));
|
|
|
|
for (j = 0; j < piicSrc->NumFlows; j++)
|
|
{
|
|
if (!_wcsicmp(pNextFlow->FlowName, pwszFlowName))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextFlow = (PIPQOS_IF_FLOW)
|
|
((PUCHAR) pNextFlow + pNextFlow->FlowSize);
|
|
}
|
|
|
|
if (j == piicSrc->NumFlows)
|
|
{
|
|
//
|
|
// We do not have a flow by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOW_NOT_FOUND,
|
|
pwszFlowName);
|
|
i = dwNumArg;
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
// Flow was found at 'pNextFlow' position
|
|
|
|
//
|
|
// Search for a QOS object by this name
|
|
//
|
|
|
|
pwszNextObject =
|
|
(PWCHAR) ((PUCHAR) pNextFlow + sizeof(IPQOS_IF_FLOW));
|
|
|
|
for (k = 0; k < pNextFlow->FlowDesc.NumTcObjects; k++)
|
|
{
|
|
if (!_wcsicmp(pwszNextObject, pwszQosObject))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pwszNextObject += MAX_STRING_LENGTH;
|
|
}
|
|
|
|
if (!bAdd)
|
|
{
|
|
//
|
|
// Make sure that the flow has the named qosobject
|
|
//
|
|
|
|
if (k == pNextFlow->FlowDesc.NumTcObjects)
|
|
{
|
|
DisplayMessage(g_hModule,
|
|
MSG_QOSOBJECT_NOT_FOUND,
|
|
pwszQosObject);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Update number of qos objects in src buff
|
|
// so that copy to dest results in new value
|
|
//
|
|
|
|
pNextFlow->FlowSize -= MAX_WSTR_LENGTH;
|
|
|
|
pNextFlow->FlowDesc.NumTcObjects--;
|
|
|
|
//
|
|
// Delete the association of the qosobject & flow
|
|
//
|
|
|
|
dwNewBlkSize = dwBlkSize - MAX_WSTR_LENGTH;
|
|
|
|
piicDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!piicDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
dwOffset = (PUCHAR)pwszNextObject - (PUCHAR)piicSrc;
|
|
|
|
// Copy the all the objects that occur before
|
|
memcpy(piicDst, piicSrc, dwOffset);
|
|
|
|
// Copy the rest of the obj names as they are
|
|
dwSkip = dwOffset + MAX_WSTR_LENGTH;
|
|
memcpy((PUCHAR) piicDst + dwOffset,
|
|
(PUCHAR) piicSrc + dwSkip,
|
|
dwBlkSize - dwSkip);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Does the flow already have this QOS object ?
|
|
//
|
|
|
|
if (k < pNextFlow->FlowDesc.NumTcObjects)
|
|
{
|
|
DisplayMessage(g_hModule,
|
|
MSG_QOSOBJECT_ALREADY_EXISTS,
|
|
pwszQosObject);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Make sure that qosobject is actually defined
|
|
//
|
|
|
|
dwErr = IpmontrGetInfoBlockFromGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE *) &pigcSrc,
|
|
&dwBlkSize1,
|
|
&dwQosCount1);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( pigcSrc == NULL )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
dwOffset = FIELD_OFFSET(IPQOS_NAMED_QOSOBJECT, QosObjectHdr);
|
|
|
|
pNextQosObject =
|
|
(PIPQOS_NAMED_QOSOBJECT)((PUCHAR) pigcSrc
|
|
+ sizeof(IPQOS_GLOBAL_CONFIG)
|
|
+ (pigcSrc->NumFlowspecs *
|
|
sizeof(IPQOS_NAMED_FLOWSPEC)));
|
|
|
|
for (l = 0; l < pigcSrc->NumQosObjects; l++)
|
|
{
|
|
if (!_wcsicmp(pNextQosObject->QosObjectName,
|
|
pwszQosObject))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextQosObject = (PIPQOS_NAMED_QOSOBJECT)
|
|
((PUCHAR) pNextQosObject +
|
|
dwOffset +
|
|
pNextQosObject->QosObjectHdr.ObjectLength);
|
|
}
|
|
|
|
if (l == pigcSrc->NumQosObjects)
|
|
{
|
|
//
|
|
// We do not have a qos object by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_QOSOBJECT_NOT_FOUND,
|
|
pwszQosObject);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Update number of qos objects in src buff
|
|
// so that copy to dest results in new value
|
|
//
|
|
|
|
pNextFlow->FlowSize += MAX_WSTR_LENGTH;
|
|
|
|
pNextFlow->FlowDesc.NumTcObjects++;
|
|
|
|
//
|
|
// Create the association of the qosobject & flow
|
|
//
|
|
|
|
dwNewBlkSize = dwBlkSize + MAX_WSTR_LENGTH;
|
|
|
|
piicDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!piicDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
dwOffset = (PUCHAR)pwszNextObject - (PUCHAR)piicSrc;
|
|
|
|
// Copy the all the objects that occur before
|
|
memcpy(piicDst, piicSrc, dwOffset);
|
|
|
|
// Copy the new association at the end of flow
|
|
wcscpy((PWCHAR)((PUCHAR) piicDst + dwOffset),
|
|
pwszQosObject);
|
|
|
|
// Copy the rest of the obj names as they are
|
|
dwSkip = dwOffset + MAX_WSTR_LENGTH;
|
|
memcpy((PUCHAR) piicDst + dwSkip,
|
|
(PUCHAR) piicSrc + dwOffset,
|
|
dwBlkSize - dwOffset);
|
|
}
|
|
|
|
// Update the interface config by setting new info
|
|
|
|
dwErr = IpmontrSetInfoBlockInInterfaceInfo(wszIfName,
|
|
MS_IP_QOSMGR,
|
|
(PBYTE) piicDst,
|
|
dwNewBlkSize,
|
|
dwQosCount);
|
|
}
|
|
while (FALSE);
|
|
|
|
HEAP_FREE_NOT_NULL(piicSrc);
|
|
HEAP_FREE_NOT_NULL(pigcSrc);
|
|
HEAP_FREE_NOT_NULL(piicDst);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
|
|
//
|
|
// Flowspec Helpers
|
|
//
|
|
|
|
DWORD
|
|
GetQosAddDelFlowspecOpt(
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
BOOL bAdd
|
|
)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
TAG_TYPE pttTags[] = {
|
|
{TOKEN_OPT_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_SERVICE_TYPE,FALSE,FALSE},
|
|
{TOKEN_OPT_TOKEN_RATE,FALSE,FALSE},
|
|
{TOKEN_OPT_TOKEN_BUCKET_SIZE,FALSE,FALSE},
|
|
{TOKEN_OPT_PEAK_BANDWIDTH,FALSE,FALSE},
|
|
{TOKEN_OPT_LATENCY,FALSE,FALSE},
|
|
{TOKEN_OPT_DELAY_VARIATION,FALSE,FALSE},
|
|
{TOKEN_OPT_MAX_SDU_SIZE,FALSE,FALSE},
|
|
{TOKEN_OPT_MIN_POLICED_SIZE,FALSE,FALSE}};
|
|
PIPQOS_NAMED_FLOWSPEC pNamedFlowspec, pNextFlowspec;
|
|
FLOWSPEC fsFlowspec, *pFlowspec;
|
|
PIPQOS_GLOBAL_CONFIG pigcSrc = NULL, pigcDst = NULL;
|
|
DWORD dwBlkSize, dwNewBlkSize, dwQosCount;
|
|
PTCHAR pszFlowspec;
|
|
DWORD dwNumOpt, dwRes;
|
|
DWORD dwNumArg, i, j;
|
|
DWORD dwSkip, dwOffset;
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
//
|
|
// We need only the name for delete
|
|
//
|
|
|
|
if (!bAdd && (dwNumArg != 1))
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
pFlowspec = &fsFlowspec;
|
|
if (bAdd)
|
|
{
|
|
//
|
|
// Initialize the flowspec definition
|
|
//
|
|
|
|
memset(pFlowspec, QOS_NOT_SPECIFIED, sizeof(FLOWSPEC));
|
|
}
|
|
|
|
//
|
|
// Process the arguments now
|
|
//
|
|
|
|
for ( i = 0; i < dwNumArg; i++)
|
|
{
|
|
// Only an flowspec name is allowed at delete
|
|
|
|
if ((!bAdd) && (pdwTagType[i] != 0))
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
|
|
// All params except the first 2 are ulong vals
|
|
|
|
if ( pdwTagType[i] > 1)
|
|
{
|
|
// What if this is not a valid ULONG ? '0' will not do...
|
|
dwRes = _tcstoul(pptcArguments[i + dwCurrentIndex],NULL,10);
|
|
}
|
|
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0 :
|
|
{
|
|
//
|
|
// FLOWSPEC_NAME : See if we already have the name
|
|
//
|
|
|
|
dwErr = IpmontrGetInfoBlockFromGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE *) &pigcSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( pigcSrc == NULL )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
pNextFlowspec = (PIPQOS_NAMED_FLOWSPEC)
|
|
((PUCHAR) pigcSrc + sizeof(IPQOS_GLOBAL_CONFIG));
|
|
|
|
for (j = 0; j < pigcSrc->NumFlowspecs; j++)
|
|
{
|
|
if (!_wcsicmp(pNextFlowspec->FlowspecName,
|
|
pptcArguments[i + dwCurrentIndex]))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextFlowspec++;
|
|
}
|
|
|
|
if (bAdd)
|
|
{
|
|
//
|
|
// Do (not) allow overwriting existing flowspecs
|
|
//
|
|
#if NO_UPDATE
|
|
if (j < pigcSrc->NumFlowspecs)
|
|
{
|
|
//
|
|
// We already have a flowspec by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOWSPEC_ALREADY_EXISTS,
|
|
pptcArguments[i + dwCurrentIndex]);
|
|
i = dwNumArg;
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
#endif
|
|
pszFlowspec = pptcArguments[i + dwCurrentIndex];
|
|
}
|
|
else
|
|
{
|
|
if (j == pigcSrc->NumFlowspecs)
|
|
{
|
|
//
|
|
// We do not have a flowspec by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOWSPEC_NOT_FOUND,
|
|
pptcArguments[i + dwCurrentIndex]);
|
|
i = dwNumArg;
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 1:
|
|
{
|
|
//
|
|
// SERVICE_TYPE
|
|
//
|
|
|
|
TOKEN_VALUE rgEnums[] =
|
|
{{TOKEN_OPT_SERVICE_BESTEFFORT, SERVICETYPE_BESTEFFORT},
|
|
{TOKEN_OPT_SERVICE_CONTROLLEDLOAD,SERVICETYPE_CONTROLLEDLOAD},
|
|
{TOKEN_OPT_SERVICE_GUARANTEED, SERVICETYPE_GUARANTEED},
|
|
{TOKEN_OPT_SERVICE_QUALITATIVE, SERVICETYPE_QUALITATIVE}};
|
|
|
|
GET_ENUM_TAG_VALUE();
|
|
|
|
pFlowspec->ServiceType = dwRes;
|
|
|
|
break;
|
|
}
|
|
|
|
case 2:
|
|
{
|
|
//
|
|
// TOKEN_RATE
|
|
//
|
|
|
|
pFlowspec->TokenRate = dwRes;
|
|
break;
|
|
}
|
|
|
|
case 3:
|
|
{
|
|
//
|
|
// TOKEN_BUCKET_SIZE
|
|
//
|
|
|
|
pFlowspec->TokenBucketSize = dwRes;
|
|
break;
|
|
}
|
|
|
|
case 4:
|
|
{
|
|
//
|
|
// PEAK_BANDWIDTH
|
|
//
|
|
|
|
pFlowspec->PeakBandwidth = dwRes;
|
|
break;
|
|
}
|
|
|
|
case 5:
|
|
{
|
|
//
|
|
// LATENCY
|
|
//
|
|
|
|
pFlowspec->Latency = dwRes;
|
|
break;
|
|
}
|
|
|
|
case 6:
|
|
{
|
|
//
|
|
// DELAY_VARIATION
|
|
//
|
|
|
|
pFlowspec->DelayVariation = dwRes;
|
|
break;
|
|
}
|
|
|
|
case 7:
|
|
{
|
|
//
|
|
// MAX_SDU_SIZE
|
|
//
|
|
|
|
pFlowspec->MaxSduSize = dwRes;
|
|
break;
|
|
}
|
|
|
|
case 8:
|
|
{
|
|
//
|
|
// MIN_POLICED_SIZE
|
|
//
|
|
|
|
pFlowspec->MinimumPolicedSize = dwRes;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#if 0
|
|
// interface name should be present
|
|
|
|
if (!pttTags[0].bPresent)
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
// if add, service type should be present
|
|
|
|
if (bAdd && (!pttTags[1].bPresent))
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
|
|
if (bAdd)
|
|
{
|
|
//
|
|
// We have a new flowspec definition - update config
|
|
//
|
|
|
|
dwNewBlkSize = dwBlkSize;
|
|
|
|
if (j == pigcSrc->NumFlowspecs)
|
|
{
|
|
// We do not already have a flowspec by this name
|
|
dwNewBlkSize += sizeof(IPQOS_NAMED_FLOWSPEC);
|
|
}
|
|
|
|
pigcDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!pigcDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
dwOffset = (PUCHAR)pNextFlowspec - (PUCHAR) pigcSrc;
|
|
|
|
// Copy all existing flowspecs to the new config
|
|
memcpy(pigcDst, pigcSrc, dwOffset);
|
|
|
|
// Stick new flowspec at the next flowspec in list
|
|
pNamedFlowspec =
|
|
(PIPQOS_NAMED_FLOWSPEC)((PUCHAR)pigcDst + dwOffset);
|
|
wcscpy(pNamedFlowspec->FlowspecName, pszFlowspec);
|
|
pNamedFlowspec->FlowspecDesc = fsFlowspec;
|
|
|
|
// Copy rest of the interface config information
|
|
dwSkip = dwOffset;
|
|
|
|
if (j == pigcSrc->NumFlowspecs)
|
|
{
|
|
pigcDst->NumFlowspecs++;
|
|
}
|
|
else
|
|
{
|
|
// We are overwriting an existing flowspec
|
|
dwSkip += sizeof(IPQOS_NAMED_FLOWSPEC);
|
|
}
|
|
|
|
memcpy((PUCHAR)pigcDst + dwOffset + sizeof(IPQOS_NAMED_FLOWSPEC),
|
|
(PUCHAR)pigcSrc + dwSkip,
|
|
dwBlkSize - dwSkip);
|
|
}
|
|
else
|
|
{
|
|
#if 1
|
|
//
|
|
// BUGBUG: What if there are dependent flows present ?
|
|
//
|
|
#endif
|
|
//
|
|
// We have to del old flowspec defn - update config
|
|
//
|
|
|
|
dwNewBlkSize = dwBlkSize - sizeof(IPQOS_NAMED_FLOWSPEC);
|
|
|
|
pigcDst = HeapAlloc(GetProcessHeap(),0,dwNewBlkSize);
|
|
if (!pigcDst)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
dwOffset = (PUCHAR)pNextFlowspec - (PUCHAR)pigcSrc;
|
|
|
|
// Copy the all the flowspecs that occur before
|
|
memcpy(pigcDst, pigcSrc, dwOffset);
|
|
|
|
// Copy the rest of the flowspecs as they are
|
|
dwSkip = dwOffset + sizeof(IPQOS_NAMED_FLOWSPEC);
|
|
memcpy((PUCHAR) pigcDst + dwOffset,
|
|
(PUCHAR) pigcSrc + dwSkip,
|
|
dwBlkSize - dwSkip);
|
|
|
|
pigcDst->NumFlowspecs--;
|
|
}
|
|
|
|
// Update the global config by setting new info
|
|
|
|
dwErr = IpmontrSetInfoBlockInGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE) pigcDst,
|
|
dwNewBlkSize,
|
|
dwQosCount);
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
UpdateAllInterfaceConfigs();
|
|
}
|
|
}
|
|
while (FALSE);
|
|
|
|
HEAP_FREE_NOT_NULL(pigcSrc);
|
|
HEAP_FREE_NOT_NULL(pigcDst);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|
|
|
|
DWORD
|
|
ShowQosFlowspecs(
|
|
IN HANDLE hFile,
|
|
IN PWCHAR wszFlowspecName
|
|
)
|
|
{
|
|
PIPQOS_GLOBAL_CONFIG pigcSrc;
|
|
DWORD dwBlkSize,dwQosCount;
|
|
DWORD dwErr, j;
|
|
PIPQOS_NAMED_FLOWSPEC pNextFlowspec;
|
|
FLOWSPEC *pFlowspec;
|
|
PWCHAR pwszFlowspecName = NULL;
|
|
PTCHAR ptszServiceType = NULL;
|
|
VALUE_TOKEN vtServiceType1[] =
|
|
{SERVICETYPE_BESTEFFORT,TOKEN_OPT_SERVICE_BESTEFFORT,
|
|
SERVICETYPE_CONTROLLEDLOAD,TOKEN_OPT_SERVICE_CONTROLLEDLOAD,
|
|
SERVICETYPE_GUARANTEED,TOKEN_OPT_SERVICE_GUARANTEED,
|
|
SERVICETYPE_QUALITATIVE,TOKEN_OPT_SERVICE_QUALITATIVE};
|
|
|
|
VALUE_STRING vtServiceType2[] =
|
|
{SERVICETYPE_BESTEFFORT,STRING_SERVICE_BESTEFFORT,
|
|
SERVICETYPE_CONTROLLEDLOAD,STRING_SERVICE_CONTROLLEDLOAD,
|
|
SERVICETYPE_GUARANTEED,STRING_SERVICE_GUARANTEED,
|
|
SERVICETYPE_QUALITATIVE,STRING_SERVICE_QUALITATIVE};
|
|
|
|
dwErr = IpmontrGetInfoBlockFromGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE *) &pigcSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
if ( pigcSrc == NULL )
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
pNextFlowspec = (PIPQOS_NAMED_FLOWSPEC) ((PUCHAR) pigcSrc +
|
|
sizeof(IPQOS_GLOBAL_CONFIG));
|
|
|
|
for (j = 0; j < pigcSrc->NumFlowspecs; j++)
|
|
{
|
|
if ((!wszFlowspecName) ||
|
|
(!_wcsicmp(pNextFlowspec->FlowspecName, wszFlowspecName)))
|
|
{
|
|
pFlowspec = &pNextFlowspec->FlowspecDesc;
|
|
|
|
//
|
|
// Print or dump the flowspec now
|
|
//
|
|
|
|
pwszFlowspecName =
|
|
MakeQuotedString(pNextFlowspec->FlowspecName);
|
|
|
|
if (pwszFlowspecName == NULL)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Get service type of flowspec
|
|
//
|
|
|
|
GetAltDisplayString(g_hModule, hFile,
|
|
pFlowspec->ServiceType,
|
|
vtServiceType1,
|
|
vtServiceType2,
|
|
NUM_VALUES_IN_TABLE(vtServiceType1),
|
|
&ptszServiceType);
|
|
|
|
if ( ptszServiceType == NULL )
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
if (hFile)
|
|
{
|
|
DisplayMessageT(DMP_QOS_DELETE_FLOWSPEC,
|
|
pwszFlowspecName);
|
|
|
|
DisplayMessageT(DMP_QOS_ADD_FLOWSPEC,
|
|
pwszFlowspecName,
|
|
ptszServiceType,
|
|
pFlowspec->TokenRate,
|
|
pFlowspec->TokenBucketSize,
|
|
pFlowspec->PeakBandwidth,
|
|
pFlowspec->Latency,
|
|
pFlowspec->DelayVariation,
|
|
pFlowspec->MaxSduSize,
|
|
pFlowspec->MinimumPolicedSize);
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(g_hModule, MSG_QOS_FLOWSPEC_INFO,
|
|
pwszFlowspecName,
|
|
ptszServiceType,
|
|
pFlowspec->TokenRate,
|
|
pFlowspec->TokenBucketSize,
|
|
pFlowspec->PeakBandwidth,
|
|
pFlowspec->Latency,
|
|
pFlowspec->DelayVariation,
|
|
pFlowspec->MaxSduSize,
|
|
pFlowspec->MinimumPolicedSize);
|
|
}
|
|
|
|
FREE_STRING_NOT_NULL( ptszServiceType ) ;
|
|
|
|
if ( pwszFlowspecName )
|
|
{
|
|
FreeQuotedString( pwszFlowspecName );
|
|
pwszFlowspecName = NULL;
|
|
}
|
|
|
|
//
|
|
// If we matched flowspec, then done
|
|
//
|
|
|
|
if (wszFlowspecName)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Advance to the next flowspec in the list
|
|
pNextFlowspec++;
|
|
}
|
|
|
|
if (dwErr == NO_ERROR)
|
|
{
|
|
if ((wszFlowspecName) && (j == pigcSrc->NumFlowspecs))
|
|
{
|
|
// We didnt find the flowspec we are looking for
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOWSPEC_NOT_FOUND,
|
|
wszFlowspecName);
|
|
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
}
|
|
}
|
|
|
|
HEAP_FREE(pigcSrc);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
GetQosAddDelFlowspecOnFlowOpt(
|
|
PTCHAR *pptcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
BOOL bAdd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Gets options for attaching and detaching
|
|
flowspecs on flows.
|
|
|
|
Arguments:
|
|
|
|
pptcArguments - Argument array
|
|
dwCurrentIndex - pptcArguments[dwCurrentIndex] is the first arg
|
|
dwArgCount - pptcArguments[dwArgCount - 1] is the last arg
|
|
bAdd - Adding or deleting flows
|
|
|
|
Return Value:
|
|
|
|
NO_ERROR
|
|
|
|
--*/
|
|
{
|
|
PIPQOS_GLOBAL_CONFIG pigcSrc = NULL;
|
|
PIPQOS_IF_CONFIG piicSrc = NULL;
|
|
DWORD dwBlkSize, dwQosCount;
|
|
DWORD dwBlkSize1, dwQosCount1;
|
|
DWORD i, j, dwErr = NO_ERROR, dwNumOpt;
|
|
DWORD dwRes;
|
|
DWORD dwSkip, dwOffset, dwSize, dwBitVector = 0;
|
|
DWORD dwIfType, dwDirection;
|
|
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
|
|
PIPQOS_NAMED_FLOWSPEC pNamedFlowspec, pNextFlowspec;
|
|
PIPQOS_IF_FLOW pNextFlow, pDestFlow;
|
|
PWCHAR pwszFlowName, pwszFlowspec;
|
|
DWORD dwNumArg,
|
|
dwBufferSize = sizeof(wszIfName);
|
|
PUCHAR pFlow;
|
|
TAG_TYPE pttTags[] = {{TOKEN_OPT_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_FLOW_NAME,TRUE,FALSE},
|
|
{TOKEN_OPT_FLOWSPEC,TRUE,FALSE},
|
|
{TOKEN_OPT_DIRECTION, FALSE, FALSE}};
|
|
DWORD pdwTagType[NUM_TAGS_IN_TABLE(pttTags)];
|
|
|
|
VERIFY_INSTALLED(MS_IP_QOSMGR, STRING_PROTO_QOS_MANAGER);
|
|
|
|
//
|
|
// parse command arguements
|
|
//
|
|
|
|
dwErr = PreprocessCommand(
|
|
g_hModule, pptcArguments, dwCurrentIndex, dwArgCount,
|
|
pttTags, sizeof(pttTags)/sizeof(TAG_TYPE),
|
|
1, NUM_TAGS_IN_TABLE(pttTags), pdwTagType
|
|
);
|
|
|
|
if ( dwErr != NO_ERROR )
|
|
{
|
|
return dwErr;
|
|
}
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
dwDirection = DIRECTION_BIDIRECTIONAL;
|
|
|
|
for ( i = 0; i < dwNumArg; i++ )
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0:
|
|
// INTERFACE NAME
|
|
IpmontrGetIfNameFromFriendlyName( pptcArguments[i + dwCurrentIndex],
|
|
wszIfName,&dwBufferSize);
|
|
break;
|
|
|
|
case 1:
|
|
// FLOW NAME
|
|
pwszFlowName = pptcArguments[i + dwCurrentIndex];
|
|
break;
|
|
|
|
case 2:
|
|
// FLOWSPEC NAME
|
|
pwszFlowspec = pptcArguments[i + dwCurrentIndex];
|
|
break;
|
|
|
|
case 3:
|
|
{
|
|
// DIRECTION
|
|
TOKEN_VALUE rgEnums[] =
|
|
{{TOKEN_OPT_DIRECTION_INBOUND, DIRECTION_INBOUND},
|
|
{TOKEN_OPT_DIRECTION_OUTBOUND, DIRECTION_OUTBOUND},
|
|
{TOKEN_OPT_DIRECTION_BIDIRECTIONAL, DIRECTION_BIDIRECTIONAL}};
|
|
|
|
GET_ENUM_TAG_VALUE();
|
|
|
|
dwDirection = dwRes;
|
|
|
|
break;
|
|
}
|
|
|
|
default:
|
|
|
|
i = dwNumArg;
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
}
|
|
|
|
do
|
|
{
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
#if 0
|
|
// interface, flow, flowspec names should be present
|
|
|
|
if ((!pttTags[0].bPresent) ||
|
|
(!pttTags[1].bPresent) ||
|
|
(!pttTags[2].bPresent))
|
|
{
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Get the interface info and check if flow already exists
|
|
//
|
|
|
|
dwErr = IpmontrGetInfoBlockFromInterfaceInfo(wszIfName,
|
|
MS_IP_QOSMGR,
|
|
(PBYTE *) &piicSrc,
|
|
&dwBlkSize,
|
|
&dwQosCount,
|
|
&dwIfType);
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( piicSrc == NULL )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
pNextFlow = (PIPQOS_IF_FLOW)((PUCHAR)piicSrc + sizeof(IPQOS_IF_CONFIG));
|
|
|
|
for (j = 0; j < piicSrc->NumFlows; j++)
|
|
{
|
|
if (!_wcsicmp(pNextFlow->FlowName, pwszFlowName))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextFlow = (PIPQOS_IF_FLOW)
|
|
((PUCHAR) pNextFlow + pNextFlow->FlowSize);
|
|
}
|
|
|
|
if (j == piicSrc->NumFlows)
|
|
{
|
|
//
|
|
// We do not have a flow by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOW_NOT_FOUND,
|
|
pwszFlowName);
|
|
i = dwNumArg;
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
// Flow was found at 'pNextFlow' position
|
|
|
|
if (!bAdd)
|
|
{
|
|
//
|
|
// Make sure that the flow has the named flowspec
|
|
//
|
|
|
|
if (dwDirection & DIRECTION_INBOUND)
|
|
{
|
|
if (_wcsicmp(pNextFlow->FlowDesc.RecvingFlowspecName,
|
|
pwszFlowspec))
|
|
{
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOWSPEC_NOT_FOUND,
|
|
pwszFlowspec);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dwDirection & DIRECTION_OUTBOUND)
|
|
{
|
|
if (_wcsicmp(pNextFlow->FlowDesc.SendingFlowspecName,
|
|
pwszFlowspec))
|
|
{
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOWSPEC_NOT_FOUND,
|
|
pwszFlowspec);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete the association of the flowspec & flow
|
|
//
|
|
|
|
if (dwDirection & DIRECTION_INBOUND)
|
|
{
|
|
pNextFlow->FlowDesc.RecvingFlowspecName[0] = L'\0';
|
|
}
|
|
|
|
if (dwDirection & DIRECTION_OUTBOUND)
|
|
{
|
|
pNextFlow->FlowDesc.SendingFlowspecName[0] = L'\0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make sure that the flowspec is actually defined
|
|
//
|
|
|
|
dwErr = IpmontrGetInfoBlockFromGlobalInfo(MS_IP_QOSMGR,
|
|
(PBYTE *) &pigcSrc,
|
|
&dwBlkSize1,
|
|
&dwQosCount1);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if ( pigcSrc == NULL )
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
pNextFlowspec = (PIPQOS_NAMED_FLOWSPEC)
|
|
((PUCHAR) pigcSrc + sizeof(IPQOS_GLOBAL_CONFIG));
|
|
|
|
for (j = 0; j < pigcSrc->NumFlowspecs; j++)
|
|
{
|
|
if (!_wcsicmp(pNextFlowspec->FlowspecName,
|
|
pwszFlowspec))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pNextFlowspec++;
|
|
}
|
|
|
|
if (j == pigcSrc->NumFlowspecs)
|
|
{
|
|
//
|
|
// We do not have a flowspec by this name
|
|
//
|
|
|
|
DisplayMessage(g_hModule,
|
|
MSG_FLOWSPEC_NOT_FOUND,
|
|
pwszFlowspec);
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Create the association of the flowspec & flow
|
|
//
|
|
|
|
if (dwDirection & DIRECTION_INBOUND)
|
|
{
|
|
wcscpy(pNextFlow->FlowDesc.RecvingFlowspecName,
|
|
pwszFlowspec);
|
|
}
|
|
|
|
if (dwDirection & DIRECTION_OUTBOUND)
|
|
{
|
|
wcscpy(pNextFlow->FlowDesc.SendingFlowspecName,
|
|
pwszFlowspec);
|
|
}
|
|
}
|
|
|
|
// Update the interface config by setting new info
|
|
|
|
dwErr = IpmontrSetInfoBlockInInterfaceInfo(wszIfName,
|
|
MS_IP_QOSMGR,
|
|
(PBYTE) piicSrc,
|
|
dwBlkSize,
|
|
dwQosCount);
|
|
}
|
|
while (FALSE);
|
|
|
|
HEAP_FREE_NOT_NULL(pigcSrc);
|
|
HEAP_FREE_NOT_NULL(piicSrc);
|
|
|
|
return (dwErr == NO_ERROR) ? ERROR_OKAY : dwErr;
|
|
}
|