Leaked source code of windows server 2003
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

/*++
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;
}