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.
 
 
 
 
 
 

3468 lines
96 KiB

/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
routing\netsh\ip\iphandle.c
Abstract:
Fns to get command options
Revision History:
Anand Mahalingam 7/10/98 Created
--*/
#include "precomp.h"
#pragma hdrstop
#undef EXTRA_DEBUG
#define SHOW_IF_FILTER 0
#define SHOW_INTERFACE 1
#define SHOW_PERSISTENTROUTE 2
extern ULONG g_ulNumTopCmds;
extern ULONG g_ulNumGroups;
extern CMD_GROUP_ENTRY g_IpCmdGroups[];
extern CMD_ENTRY g_IpCmds[];
DWORD
PreHandleCommand(
IN LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN TAG_TYPE *pttTags,
IN DWORD dwTagCount,
IN DWORD dwMinArgs,
IN DWORD dwMaxArgs,
OUT DWORD *pdwTagType
)
{
ZeroMemory(pdwTagType, sizeof(DWORD) * dwMaxArgs);
return PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
dwTagCount,
dwMinArgs,
dwMaxArgs,
pdwTagType);
}
DWORD
HandleIpUpdate(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Updates IP autostatic routes on an interface
Arguments:
Return Value:
NO_ERROR
--*/
{
TAG_TYPE rgTags[] = {TOKEN_NAME, TRUE,FALSE};
DWORD dwErr, dwSize, dwTagType = -1;
WCHAR rgwcIfName[MAX_INTERFACE_NAME_LEN+1];
if (dwArgCount != 3)
{
//
// Need the name of the interface
//
return ERROR_INVALID_SYNTAX;
}
dwErr = MatchTagsInCmdLine(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
rgTags,
sizeof(rgTags)/sizeof(TAG_TYPE),
&dwTagType);
if(dwErr isnot NO_ERROR)
{
if(dwErr is ERROR_INVALID_OPTION_TAG)
{
return ERROR_INVALID_SYNTAX;
}
return dwErr;
}
if(dwTagType isnot 0)
{
return ERROR_INVALID_SYNTAX;
}
dwSize = sizeof(rgwcIfName);
IpmontrGetIfNameFromFriendlyName(ppwcArguments[dwCurrentIndex],
rgwcIfName,
&dwSize);
dwErr = UpdateAutoStaticRoutes(rgwcIfName);
return dwErr;
}
// (almost) borrowed from netsh\if\utils.c
// compares dwAddress against all valid masks (all 33 of them!) till a match
BOOL ValidMask(DWORD dwAddress)
{
DWORD i, dwMask;
dwAddress = ntohl(dwAddress); // dwAddress is in network byte order
for (i=0, dwMask=0; i<33; (dwMask = ((dwMask>>1) + 0x80000000)), i++)
{
if (dwAddress == dwMask)
return TRUE;
}
return FALSE;
}
DWORD
IpAddDelIfFilter(
PWCHAR *ppwcArguments,
DWORD dwCurrentIndex,
DWORD dwArgCount,
BOOL bAdd
)
/*++
Routine Description:
Gets options for add/del interface filters
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
bAdd - To add or to delete
Return Value:
NO_ERROR
--*/
{
FILTER_INFO fi;
DWORD dwBitVector = 0, dwNumParsed = 0;
DWORD dwErr = NO_ERROR,dwRes;
PDWORD pdwTagType;
DWORD dwNumOpt, dwStatus = (DWORD) -1;
DWORD dwNumTags = 11, dwNumArg, i, j, dwFilterType;
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
BOOL bTags = FALSE, bOkay = TRUE;
TAG_TYPE pttTags[] = {{TOKEN_NAME,TRUE,FALSE},
{TOKEN_FILTER_TYPE,TRUE,FALSE},
{TOKEN_SOURCE_ADDRESS,TRUE,FALSE},
{TOKEN_SOURCE_MASK,TRUE,FALSE},
{TOKEN_DEST_ADDRESS,TRUE,FALSE},
{TOKEN_DEST_MASK,TRUE,FALSE},
{TOKEN_PROTOCOL,TRUE,FALSE},
{TOKEN_SOURCE_PORT,TRUE,FALSE},
{TOKEN_DEST_PORT,TRUE,FALSE},
{TOKEN_TYPE,TRUE,FALSE},
{TOKEN_CODE,TRUE,FALSE}};
if (dwCurrentIndex >= dwArgCount)
{
//
// No arguments specified
//
return ERROR_SHOW_USAGE;
}
ZeroMemory(&fi, sizeof(fi));
dwNumArg = dwArgCount - dwCurrentIndex;
pdwTagType = HeapAlloc(GetProcessHeap(),
0,
dwNumArg * sizeof(DWORD));
if (pdwTagType is NULL)
{
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY);
return ERROR_NOT_ENOUGH_MEMORY;
}
dwErr = MatchTagsInCmdLine(g_hModule, ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
dwNumTags,
pdwTagType);
if (dwErr isnot NO_ERROR)
{
if (dwErr is ERROR_INVALID_OPTION_TAG)
{
dwErr = ERROR_INVALID_SYNTAX; // show usage
}
HeapFree(GetProcessHeap(),0,pdwTagType);
return dwErr;
}
bTags = TRUE;
for ( i = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case 0 :
{
DWORD BufLen = sizeof(wszIfName);
GetInterfaceName(ppwcArguments[i + dwCurrentIndex],
wszIfName,
BufLen,
&dwNumParsed);
// no filters allowed on INTERNAL/LOOPBACK interfaces
if (!_wcsicmp(wszIfName, L"internal") or
!_wcsicmp(wszIfName, L"loopback"))
{
DisplayMessage(g_hModule,
MSG_IP_BAD_INTERFACE_TYPE,
wszIfName);
dwErr = ERROR_INVALID_PARAMETER;
i = dwNumArg;
}
break;
}
case 1:
{
TOKEN_VALUE rgEnums[] =
{{TOKEN_VALUE_INPUT, IP_IN_FILTER_INFO},
{TOKEN_VALUE_OUTPUT, IP_OUT_FILTER_INFO},
{TOKEN_VALUE_DIAL, IP_DEMAND_DIAL_FILTER_INFO}};
//
// Tag FILTERTYPE
//
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
rgEnums,
&dwRes);
if(dwErr != NO_ERROR)
{
DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
DisplayMessage( g_hModule,
MSG_IP_BAD_OPTION_ENUMERATION,
pttTags[pdwTagType[i]].pwszTag );
for (i=0; i<sizeof(rgEnums)/sizeof(TOKEN_VALUE); i++)
{
DisplayMessageT( L" %1!s!\n", rgEnums[i].pwszToken );
}
i = dwNumArg;
dwErr = NO_ERROR;
bOkay = FALSE;
break;
}
dwFilterType = dwRes;
break;
}
case 2:
{
dwErr = GetIpAddress(ppwcArguments[i + dwCurrentIndex], &fi.dwSrcAddr);
if(dwErr is ERROR_INVALID_PARAMETER)
{
DisplayMessage(g_hModule, MSG_IP_BAD_IP_ADDR,
ppwcArguments[i + dwCurrentIndex]);
DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
dwErr = ERROR_INVALID_PARAMETER;
i = dwNumArg;
break;
}
//
// Get the src mask too.
//
if (pdwTagType[i+1] != 3)
{
//
// Addr Mask pair not present
//
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
dwErr = GetIpAddress(ppwcArguments[i + 1 + dwCurrentIndex],
&fi.dwSrcMask);
if ((dwErr is ERROR_INVALID_PARAMETER) or
(!ValidMask(fi.dwSrcMask)) or
((fi.dwSrcAddr & fi.dwSrcMask) isnot fi.dwSrcAddr))
{
DisplayMessage(g_hModule, MSG_IP_BAD_IP_ADDR,
ppwcArguments[i + 1 + dwCurrentIndex]);
DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i + 1]].pwszTag,
ppwcArguments[i + dwCurrentIndex + 1]);
dwErr = ERROR_INVALID_PARAMETER;
i = dwNumArg;
break;
}
i++;
break;
}
case 4 :
{
dwErr = GetIpAddress(ppwcArguments[i + dwCurrentIndex],
&fi.dwDstAddr);
if(dwErr is ERROR_INVALID_PARAMETER)
{
DisplayMessage(g_hModule, MSG_IP_BAD_IP_ADDR,
ppwcArguments[i + dwCurrentIndex]);
DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
dwErr = ERROR_INVALID_PARAMETER;
i = dwNumArg;
break;
}
//
// Get the dst mask too.
//
if (pdwTagType[i+1] != 5)
{
//
// Addr Mask pair not present
//
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
dwErr = GetIpAddress(ppwcArguments[i + 1 + dwCurrentIndex],
&fi.dwDstMask);
if ((dwErr is ERROR_INVALID_PARAMETER) or
(!ValidMask(fi.dwDstMask)) or
((fi.dwDstAddr & fi.dwDstMask) isnot fi.dwDstAddr))
{
DisplayMessage(g_hModule, MSG_IP_BAD_IP_ADDR,
ppwcArguments[i + 1 + dwCurrentIndex]);
DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i + 1]].pwszTag,
ppwcArguments[i + 1 + dwCurrentIndex]);
dwErr = ERROR_INVALID_PARAMETER;
i = dwNumArg;
break;
}
i++;
break;
}
case 6:
{
TOKEN_VALUE rgEnums[] =
{
{TOKEN_VALUE_ANY, FILTER_PROTO_ANY},
{TOKEN_VALUE_TCP, FILTER_PROTO_TCP},
{TOKEN_VALUE_TCP_ESTAB, FILTER_PROTO_TCP},
{TOKEN_VALUE_UDP, FILTER_PROTO_UDP},
{TOKEN_VALUE_ICMP, FILTER_PROTO_ICMP}
};
if (MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
rgEnums,
&dwRes) != NO_ERROR)
{
//
// In this case see if its a valid value
//
dwRes = wcstoul(ppwcArguments[i + dwCurrentIndex],
NULL,
10);
if((dwRes < 1) ||
(dwRes > 255))
{
DispTokenErrMsg(g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
DisplayMessage( g_hModule,
MSG_IP_BAD_OPTION_ENUMERATION,
pttTags[pdwTagType[i]].pwszTag );
for (i=0; i<sizeof(rgEnums)/sizeof(TOKEN_VALUE); i++)
{
DisplayMessageT( L" %1!s!\n", rgEnums[i].pwszToken );
}
i = dwNumArg;
dwErr = NO_ERROR;
bOkay = FALSE;
break;
}
}
fi.dwProtocol = dwRes;
switch (fi.dwProtocol)
{
case FILTER_PROTO_ANY :
//
// We are done
//
fi.wSrcPort = fi.wDstPort = 0;
break;
case FILTER_PROTO_TCP :
// TCP and TCP_ESTABLISHED have same protocol number
if (!MatchToken(ppwcArguments[i + dwCurrentIndex],
TOKEN_VALUE_TCP))
{
fi.fLateBound |= TCP_ESTABLISHED_FLAG;
}
// continue processing as we could for UDP...
case FILTER_PROTO_UDP :
//
// Get the src and dst ports too
//
if (i + 2 >= dwNumArg)
{
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
if (bTags &&
(pdwTagType[i+1] != 7 || pdwTagType[i+2] != 8))
{
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
fi.wSrcPort =
htons((WORD)wcstoul(ppwcArguments[i + 1 + dwCurrentIndex],
NULL,
10));
fi.wDstPort =
htons((WORD)wcstoul(ppwcArguments[i + 2 + dwCurrentIndex],
NULL,
10));
i += 2;
break;
case FILTER_PROTO_ICMP :
//
// Get the src and dst ports too
//
if (i + 2 >= dwNumArg)
{
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
// src and dest ports acted upon as type and code
if (bTags &&
(pdwTagType[i+1] != 7 || pdwTagType[i+2] != 8) &&
(pdwTagType[i+1] != 9 || pdwTagType[i+2] != 10))
{
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
fi.wSrcPort = (BYTE)wcstoul(ppwcArguments[i + 1 + dwCurrentIndex], NULL, 10);
fi.wDstPort = (BYTE)wcstoul(ppwcArguments[i + 2 + dwCurrentIndex], NULL, 10);
i += 2;
break;
default:
{
//
// any 'other' protocol
//
fi.wSrcPort = fi.wDstPort = 0;
break;
}
}
break;
}
default:
{
i = dwNumArg;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
}
HeapFree(GetProcessHeap(), 0, pdwTagType);
switch(dwErr)
{
case NO_ERROR :
break;
default:
return dwErr;
}
if (!bOkay)
{
return NO_ERROR;
}
//
// Make sure all parameters are present
//
if ( !pttTags[0].bPresent ||
!pttTags[1].bPresent ||
!pttTags[2].bPresent ||
!pttTags[3].bPresent ||
!pttTags[4].bPresent ||
!pttTags[5].bPresent ||
!pttTags[6].bPresent )
{
DisplayMessage(g_hModule, MSG_CANT_FIND_EOPT);
return ERROR_INVALID_SYNTAX;
}
dwErr = AddDelFilterInfo(fi,
wszIfName,
dwFilterType,
bAdd);
return dwErr;
}
DWORD
HandleIpAddIfFilter(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Gets options for add interface filters
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
return IpAddDelIfFilter(ppwcArguments,
dwCurrentIndex,
dwArgCount,
TRUE);
}
DWORD
HandleIpDelIfFilter(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Gets options for del interface filters
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
return IpAddDelIfFilter(ppwcArguments,
dwCurrentIndex,
dwArgCount,
FALSE);
}
DWORD
IpAddSetDelRtmRoute(
PWCHAR *ppwcArguments,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwCommand
)
/*++
Routine Description:
Gets options for add/del routes over interfaces.
These operations are performed directly to RTM
and do not involve the registry. As persistence
is not involved, we need the router to be running.
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
dwCommand - To add, set, or delete
Return Value:
NO_ERROR
--*/
{
INTERFACE_ROUTE_INFO route;
DWORD dwNumParsed, dwErr, dwRes;
DWORD dwNumOpt, dwStatus = (DWORD) -1;
DWORD dwNumArg, i;
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
TAG_TYPE pttTags[] = {{TOKEN_DEST,TRUE,FALSE},
{TOKEN_MASK,FALSE,FALSE},
{TOKEN_NAMEINDEX,FALSE,FALSE},
{TOKEN_NHOP,FALSE,FALSE},
{TOKEN_PREFERENCE,FALSE,FALSE},
{TOKEN_METRIC,FALSE,FALSE},
{TOKEN_VIEW,FALSE,FALSE}};
enum idx {DEST, MASK, NAMEINDEX, NHOP, PREFERENCE, METRIC, VIEW};
DWORD pdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD dwMaxArgs;
DWORD dwIfClass;
DWORD dwFlags;
PINTERFACE_ROUTE_INFO pTable = NULL;
//
// We can add non persistent routes only if router is running
//
CHECK_ROUTER_RUNNING();
ZeroMemory(&route,
sizeof(route));
route.dwRtInfoProto = PROTO_IP_NETMGMT; // default proto
route.dwRtInfoPreference = 0; // default preference = protocol default
route.dwRtInfoMetric1 = 1; // default metric
route.dwRtInfoMetric2 = MIB_IPROUTE_METRIC_UNUSED;
route.dwRtInfoMetric3 = MIB_IPROUTE_METRIC_UNUSED;
route.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST;
// Do generic processing
dwErr = PreHandleCommand( ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
1,
sizeof(pttTags)/sizeof(TAG_TYPE),
pdwTagType );
if (dwErr)
{
return dwErr;
}
dwNumArg = dwArgCount - dwCurrentIndex;
//
// At this point, the arg array contains only values (either because
// the tags werent present, or because that info has now been split out)
// So we go through each of the each of the arguments, look up its tag
// type in the tag array, switch on the type of tag it is and then
// process accordingly.
//
for (i = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case DEST: // DEST
{
dwErr = GetIpPrefix(ppwcArguments[i + dwCurrentIndex],
&route.dwRtInfoDest,
&route.dwRtInfoMask);
break;
}
case MASK: // MASK
{
dwErr = GetIpMask(ppwcArguments[i + dwCurrentIndex],
&route.dwRtInfoMask);
break;
}
case NAMEINDEX : // INDEX or NAME
{
PWCHAR endptr = NULL;
DWORD BufLen;
//
// Initially consider the user input to be the friendly name of the
// interface
// If we fail to get the interface name from this friendly name
// then we shall try considering the user as an index
//
route.dwRtInfoIfIndex = 0;
BufLen = sizeof(wszIfName);
dwErr = GetInterfaceName(ppwcArguments[i + dwCurrentIndex],
wszIfName,
BufLen,
&dwNumParsed);
if (dwErr != NO_ERROR)
{
// If it starts with '0x', this is a hex index
// else if it starts with 0, this is an 0ctal index
// else it is decimal or an interface name
//
if ((ppwcArguments[i + dwCurrentIndex][0] == L'0') &&
(ppwcArguments[i + dwCurrentIndex][1] == L'x'))
{
route.dwRtInfoIfIndex =
wcstoul(ppwcArguments[i + dwCurrentIndex],
&endptr,
16);
}
else if ( ppwcArguments[i + dwCurrentIndex][0] == L'0')
{
route.dwRtInfoIfIndex =
wcstoul(ppwcArguments[i + dwCurrentIndex],
&endptr,
8);
}
else
{
route.dwRtInfoIfIndex =
wcstoul(ppwcArguments[i + dwCurrentIndex],
&endptr,
10);
}
//
// If all the characters in the field were not used while doing the
// conversion, then we know that the input was not purely
/// numeric, and is thus invalid as an index value
//
if (*endptr != L'\0')
{
DisplayMessage(g_hModule, EMSG_CANT_MATCH_NAME);
return ERROR_INVALID_PARAMETER;
}
}
break;
}
case NHOP: // NHOP
{
dwErr = GetIpAddress(ppwcArguments[i + dwCurrentIndex],
&route.dwRtInfoNextHop);
break;
}
case PREFERENCE:
{
route.dwRtInfoPreference =
wcstoul(ppwcArguments[i + dwCurrentIndex],
NULL,
10);
break;
}
case METRIC: // METRIC
{
route.dwRtInfoMetric1 =
wcstoul(ppwcArguments[i + dwCurrentIndex],
NULL,
10);
break;
}
case VIEW:
{
TOKEN_VALUE rgMaskEnums[] = {
{ TOKEN_VALUE_UNICAST, RTM_VIEW_MASK_UCAST },
{ TOKEN_VALUE_MULTICAST, RTM_VIEW_MASK_MCAST },
{ TOKEN_VALUE_BOTH, RTM_VIEW_MASK_UCAST
|RTM_VIEW_MASK_MCAST } };
dwErr = MatchEnumTag( g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgMaskEnums)/sizeof(TOKEN_VALUE),
rgMaskEnums,
&route.dwRtInfoViewSet);
if (dwErr isnot NO_ERROR)
{
DispTokenErrMsg( g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex] );
i = dwArgCount;
return ERROR_INVALID_PARAMETER;
}
break;
}
}
}
if (dwErr)
{
return dwErr;
}
if (route.dwRtInfoDest & ~route.dwRtInfoMask)
{
// Mask contains bits not in address
DisplayMessage(g_hModule, EMSG_PREFIX_ERROR);
return ERROR_INVALID_PARAMETER;
}
if (!pttTags[NAMEINDEX].bPresent)
{
//
// Neither NAME nor INDEX - adding with a nexthop
//
PMIB_IPADDRTABLE AddrTable;
PMIB_IPADDRROW AddrEntry;
MIB_OPAQUE_QUERY Query;
PMIB_OPAQUE_INFO Info;
DWORD dwQuerySize;
DWORD dwEntrySize;
INT iFirstMatch;
UINT Count;
if (!pttTags[NHOP].bPresent)
{
DisplayMessage(g_hModule, EMSG_CANT_FIND_NAME_OR_NHOP);
return ERROR_INVALID_SYNTAX;
}
//
// Search for the interface that matches nexthop
//
dwQuerySize = sizeof(MIB_OPAQUE_QUERY) - sizeof(DWORD);
Query.dwVarId = IP_ADDRTABLE;
dwErr = MibGet(PID_IP,
IPRTRMGR_PID,
(PVOID) &Query,
dwQuerySize,
(PVOID *) &Info,
&dwEntrySize);
if (dwErr != NO_ERROR)
{
DisplayMessage(g_hModule, MSG_IP_DIM_ERROR, dwErr);
return ERROR_SUPPRESS_OUTPUT;
}
if (Info is NULL)
{
DisplayMessage(g_hModule, EMSG_CANT_FIND_INDEX);
return ERROR_INVALID_PARAMETER;
}
AddrTable = (PMIB_IPADDRTABLE)Info->rgbyData;
iFirstMatch = -1;
for (Count = 0; Count < AddrTable->dwNumEntries; Count++)
{
AddrEntry = &AddrTable->table[Count];
if ((route.dwRtInfoNextHop & AddrEntry->dwMask) ==
(AddrEntry->dwAddr & AddrEntry->dwMask))
{
if (iFirstMatch != -1)
{
//
// We already matched an interface
// [Ambiguous next hop description]
//
MprAdminMIBBufferFree((PVOID)Info);
DisplayMessage(g_hModule, EMSG_AMBIGUOUS_INDEX_FROM_NHOP);
return ERROR_INVALID_PARAMETER;
}
iFirstMatch = Count;
}
}
if (iFirstMatch == -1)
{
//
// Could not find the direct nexthop
//
MprAdminMIBBufferFree((PVOID)Info);
DisplayMessage(g_hModule, EMSG_CANT_FIND_INDEX);
return ERROR_INVALID_PARAMETER;
}
//
// Found the interface used to reach nexthop
//
route.dwRtInfoIfIndex = AddrTable->table[iFirstMatch].dwIndex;
MprAdminMIBBufferFree((PVOID)Info);
}
if (route.dwRtInfoIfIndex)
{
//
// Check if this index has a public exported name
//
dwErr = GetGuidFromIfIndex(g_hMIBServer,
route.dwRtInfoIfIndex,
wszIfName,
MAX_INTERFACE_NAME_LEN);
if ( dwErr != NO_ERROR )
{
DisplayMessage(g_hModule, EMSG_CANT_FIND_INDEX);
return ERROR_INVALID_PARAMETER;
}
}
if (wszIfName[0] != L'\0')
{
//
// NAME specified, or derived from INDEX above
//
dwErr = GetInterfaceClass(wszIfName, &dwIfClass);
//
// If we get an error, we will skip remaining
// checks which will be performed by iprtrmgr
//
if (dwErr == NO_ERROR)
{
if (dwIfClass is IFCLASS_LOOPBACK)
{
return ERROR_INVALID_SYNTAX;
}
if (!pttTags[NHOP].bPresent)
{
// Make sure interface is p2p
if (dwIfClass isnot IFCLASS_P2P)
{
DisplayMessage(g_hModule, EMSG_NEED_NHOP);
return ERROR_INVALID_PARAMETER;
}
}
}
}
else
{
DisplayMessage(g_hModule, EMSG_CANT_MATCH_NAME);
return ERROR_INVALID_PARAMETER;
}
//
// If it is a set, we should not overwrite things not specified
//
dwFlags = ALL_FIELDS_SPECIFIED;
if (dwCommand == SET_COMMAND)
{
if (!pttTags[PREFERENCE].bPresent) dwFlags |= PREF_NOT_SPECIFIED;
if (!pttTags[METRIC].bPresent) dwFlags |= METRIC_NOT_SPECIFIED;
if (!pttTags[VIEW].bPresent) dwFlags |= VIEW_NOT_SPECIFIED;
}
return AddSetDelRtmRouteInfo(&route, wszIfName, dwCommand, dwFlags);
}
DWORD
HandleIpAddRtmRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelRtmRoute(ppwcArguments,
dwCurrentIndex,
dwArgCount,
ADD_COMMAND);
}
DWORD
HandleIpDelRtmRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelRtmRoute(ppwcArguments,
dwCurrentIndex,
dwArgCount,
DELETE_COMMAND);
}
DWORD
HandleIpSetRtmRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelRtmRoute(ppwcArguments,
dwCurrentIndex,
dwArgCount,
SET_COMMAND);
}
DWORD
IpAddSetDelPersistentRoute(
PWCHAR *ppwcArguments,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwCommand
)
/*++
Routine Description:
Gets options for add/del routes over interfaces.
These operations are performed directly to the
registry and so these routes are persistent. If
the router is running, they go into the RTM too.
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
dwCommand - To add, set, or delete
Return Value:
NO_ERROR
--*/
{
INTERFACE_ROUTE_INFO route;
DWORD dwNumParsed, dwErr, dwRes;
DWORD dwNumOpt, dwStatus = (DWORD) -1;
DWORD dwNumArg, i;
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
WCHAR *pwszIfNameOnCmdLine = NULL;
TAG_TYPE pttTags[] = {{TOKEN_DEST,TRUE,FALSE},
{TOKEN_MASK,FALSE,FALSE},
{TOKEN_NAME,FALSE,FALSE},
{TOKEN_NHOP,FALSE,FALSE},
{TOKEN_PROTOCOL,FALSE,FALSE},
{TOKEN_PREFERENCE,FALSE,FALSE},
{TOKEN_METRIC,FALSE,FALSE},
{TOKEN_VIEW,FALSE,FALSE}};
enum idx {DEST, MASK, NAME, NHOP, PROTO, PREFERENCE, METRIC, VIEW};
DWORD pdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD dwMaxArgs;
DWORD dwIfClass;
DWORD dwFlags;
PINTERFACE_ROUTE_INFO pTable = NULL;
ZeroMemory(&route,
sizeof(route));
route.dwRtInfoProto = PROTO_IP_NT_STATIC_NON_DOD; // default proto
route.dwRtInfoPreference = 0; // default preference = protocol default
route.dwRtInfoMetric1 = 1; // default metric
route.dwRtInfoMetric2 = MIB_IPROUTE_METRIC_UNUSED;
route.dwRtInfoMetric3 = MIB_IPROUTE_METRIC_UNUSED;
route.dwRtInfoViewSet = RTM_VIEW_MASK_UCAST | RTM_VIEW_MASK_MCAST;
// Do generic processing
dwErr = PreHandleCommand( ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
1,
sizeof(pttTags)/sizeof(TAG_TYPE),
pdwTagType );
if (dwErr)
{
return dwErr;
}
dwNumArg = dwArgCount - dwCurrentIndex;
//
// At this point, the arg array contains only values (either because
// the tags werent present, or because that info has now been split out)
// So we go through each of the each of the arguments, look up its tag
// type in the tag array, switch on the type of tag it is and then
// process accordingly.
//
for (i = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case DEST: // DEST
{
dwErr = GetIpPrefix(ppwcArguments[i + dwCurrentIndex],
&route.dwRtInfoDest,
&route.dwRtInfoMask);
break;
}
case MASK: // MASK
{
dwErr = GetIpMask(ppwcArguments[i + dwCurrentIndex],
&route.dwRtInfoMask);
break;
}
case NAME : // NAME
{
DWORD BufLen = sizeof(wszIfName);
pwszIfNameOnCmdLine = ppwcArguments[i + dwCurrentIndex];
GetInterfaceName(ppwcArguments[i + dwCurrentIndex],
wszIfName,
BufLen,
&dwNumParsed);
break;
}
case NHOP: // NHOP
{
dwErr = GetIpAddress(ppwcArguments[i + dwCurrentIndex],
&route.dwRtInfoNextHop);
break;
}
case PROTO : // PROTO
{
TOKEN_VALUE rgEnums[] =
{/*{TOKEN_VALUE_AUTOSTATIC, PROTO_IP_NT_AUTOSTATIC},*/
{TOKEN_VALUE_STATIC, PROTO_IP_NT_STATIC},
{TOKEN_VALUE_NONDOD, PROTO_IP_NT_STATIC_NON_DOD}};
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
rgEnums,
&dwRes);
if (dwErr != NO_ERROR)
{
DispTokenErrMsg(g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
DisplayMessage( g_hModule,
MSG_IP_BAD_OPTION_ENUMERATION,
pttTags[pdwTagType[i]].pwszTag );
for (i=0; i<sizeof(rgEnums)/sizeof(TOKEN_VALUE); i++)
{
DisplayMessageT( L" %1!s!\n", rgEnums[i].pwszToken );
}
return ERROR_SUPPRESS_OUTPUT;
}
route.dwRtInfoProto = dwRes;
break;
}
case PREFERENCE:
{
route.dwRtInfoPreference =
wcstoul(ppwcArguments[i + dwCurrentIndex],
NULL,
10);
break;
}
case METRIC:
{
route.dwRtInfoMetric1 =
wcstoul(ppwcArguments[i + dwCurrentIndex],
NULL,
10);
break;
}
case VIEW:
{
TOKEN_VALUE rgMaskEnums[] = {
{ TOKEN_VALUE_UNICAST, RTM_VIEW_MASK_UCAST },
{ TOKEN_VALUE_MULTICAST, RTM_VIEW_MASK_MCAST },
{ TOKEN_VALUE_BOTH, RTM_VIEW_MASK_UCAST
|RTM_VIEW_MASK_MCAST } };
dwErr = MatchEnumTag( g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgMaskEnums)/sizeof(TOKEN_VALUE),
rgMaskEnums,
&route.dwRtInfoViewSet);
if (dwErr isnot NO_ERROR)
{
DispTokenErrMsg( g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex] );
i = dwArgCount;
return ERROR_SUPPRESS_OUTPUT;
}
break;
}
}
}
if (dwErr)
{
return dwErr;
}
if (route.dwRtInfoDest & ~route.dwRtInfoMask)
{
// Mask contains bits not in address
DisplayMessage(g_hModule, EMSG_PREFIX_ERROR);
return ERROR_SUPPRESS_OUTPUT;
}
if (!pttTags[NAME].bPresent)
{
// Need if name to add persistent route
DisplayMessage(g_hModule, EMSG_CANT_FIND_NAME);
return ERROR_SUPPRESS_OUTPUT;
}
dwErr = GetInterfaceClass(wszIfName, &dwIfClass);
if (dwErr)
{
DisplayMessage(g_hModule, EMSG_CANT_GET_IF_INFO,
pwszIfNameOnCmdLine,
dwErr);
return ERROR_SUPPRESS_OUTPUT;
}
if (dwIfClass is IFCLASS_LOOPBACK)
{
return ERROR_INVALID_SYNTAX;
}
if (!pttTags[NHOP].bPresent)
{
// Make sure interface is p2p
if (dwIfClass isnot IFCLASS_P2P)
{
DisplayMessage(g_hModule, EMSG_NEED_NHOP);
return ERROR_SUPPRESS_OUTPUT;
}
}
if (dwIfClass is IFCLASS_P2P)
{
if (!pttTags[PROTO].bPresent)
{
// if not explicitly specified, change protocol to static
route.dwRtInfoProto = PROTO_IP_NT_STATIC; // default proto
}
// Make sure nhop is not specified.
if (pttTags[NHOP].bPresent)
{
// if class is p2p, then nhop specification is not allowed
DisplayMessage(g_hModule, EMSG_P2P_WITH_NHOP,
pwszIfNameOnCmdLine);
return ERROR_SUPPRESS_OUTPUT;
}
}
else
{
// make sure we didn't try to set static on a non-P2P interface
if (route.dwRtInfoProto is PROTO_IP_NT_STATIC)
{
return ERROR_INVALID_PARAMETER;
}
}
//
// If it is a set, we should not overwrite things not specified
//
dwFlags = ALL_FIELDS_SPECIFIED;
if (dwCommand == SET_COMMAND)
{
if (!pttTags[PREFERENCE].bPresent) dwFlags |= PREF_NOT_SPECIFIED;
if (!pttTags[METRIC].bPresent) dwFlags |= METRIC_NOT_SPECIFIED;
if (!pttTags[VIEW].bPresent) dwFlags |= VIEW_NOT_SPECIFIED;
}
return AddSetDelPersistentRouteInfo(&route, wszIfName, dwCommand, dwFlags);
}
DWORD
HandleIpAddPersistentRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelPersistentRoute(ppwcArguments,
dwCurrentIndex,
dwArgCount,
ADD_COMMAND);
}
DWORD
HandleIpDelPersistentRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelPersistentRoute(ppwcArguments,
dwCurrentIndex,
dwArgCount,
DELETE_COMMAND);
}
DWORD
HandleIpSetPersistentRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelPersistentRoute(ppwcArguments,
dwCurrentIndex,
dwArgCount,
SET_COMMAND);
}
DWORD
HandleIpAddRoutePref(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Gets options for adding route preferences
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
PPROTOCOL_METRIC ppm;
DWORD dwBitVector = 0, dwNumPref,dwPrefIndex;
DWORD dwErr = NO_ERROR,dwRes;
PDWORD pdwTagType;
DWORD dwNumTags = 2, dwNumArg, i, dwAddr;
TAG_TYPE pttTags[] = {{TOKEN_PROTOCOL, TRUE,FALSE},
{TOKEN_PREF_LEVEL, TRUE,FALSE}};
if (dwCurrentIndex >= dwArgCount)
{
//
// No arguments specified
//
return ERROR_SHOW_USAGE;
}
dwNumArg = dwArgCount - dwCurrentIndex;
pdwTagType = HeapAlloc(GetProcessHeap(),
0,
dwNumArg * sizeof(DWORD));
if (pdwTagType is NULL)
{
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY);
return ERROR_NOT_ENOUGH_MEMORY;
}
dwErr = MatchTagsInCmdLine(g_hModule, ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
dwNumTags,
pdwTagType);
if (dwErr isnot NO_ERROR)
{
HeapFree(GetProcessHeap(),0,pdwTagType);
if (dwErr is ERROR_INVALID_OPTION_TAG)
{
dwErr = ERROR_INVALID_SYNTAX; // show usage
}
return dwErr;
}
dwNumPref = dwNumArg / 2 + dwNumArg % 2;
ppm = HeapAlloc(GetProcessHeap(),
0,
dwNumPref * sizeof(PROTOCOL_METRIC));
if (ppm is NULL)
{
HeapFree(GetProcessHeap(),0,pdwTagType);
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY);
return ERROR_SUPPRESS_OUTPUT;
}
for ( i = 0, dwPrefIndex = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case 0:
{
//
// TAG = PROTOCOL
//
dwRes = MatchRoutingProtoTag(ppwcArguments[i + dwCurrentIndex]);
if (dwRes == (DWORD) -1)
{
DispTokenErrMsg(g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
i = dwNumArg;
dwErr = ERROR_SUPPRESS_OUTPUT;
break;
}
ppm[dwPrefIndex].dwProtocolId = dwRes;
//
// Get the metric too
//
if (pdwTagType[i+1] == 1)
{
ppm[dwPrefIndex].dwMetric =
wcstoul(ppwcArguments[i + 1 +dwCurrentIndex],NULL,10);
if (ppm[dwPrefIndex].dwMetric==0
&& wcscmp(ppwcArguments[i + 1 +dwCurrentIndex], L"0")!=0)
{
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
i++;
dwPrefIndex++;
}
else
{
//
// the range is not an addr mask pair.
// So ignore the addr (i.e. don't increment dwRangeIndex)
//
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
break;
}
default :
{
i = dwNumArg;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
}
HeapFree(GetProcessHeap(), 0, pdwTagType);
switch(dwErr)
{
case NO_ERROR :
break;
default:
return dwErr;
}
if (dwPrefIndex)
{
//
// Add route pref
//
dwRes = AddDeleteRoutePrefLevel(ppm,
dwPrefIndex,
TRUE);
}
HeapFree(GetProcessHeap(), 0, ppm);
return dwErr;
}
DWORD
HandleIpDelRoutePref(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Gets options for deleting route preferences
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
PPROTOCOL_METRIC ppm;
DWORD dwBitVector = 0, dwNumPref,dwPrefIndex;
DWORD dwErr = NO_ERROR,dwRes;
TAG_TYPE pttTags[] = {{TOKEN_PROTOCOL,TRUE,FALSE}};
PDWORD pdwTagType;
DWORD dwNumTags = 1, dwNumArg, i, dwAddr;
if (dwCurrentIndex >= dwArgCount)
{
//
// No arguments specified
//
return ERROR_SHOW_USAGE;
}
dwNumArg = dwArgCount - dwCurrentIndex;
pdwTagType = HeapAlloc(GetProcessHeap(),
0,
dwNumArg * sizeof(DWORD));
if (pdwTagType is NULL)
{
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY);
return ERROR_SUPPRESS_OUTPUT;
}
dwErr = MatchTagsInCmdLine(g_hModule, ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
dwNumTags,
pdwTagType);
if (dwErr isnot NO_ERROR)
{
HeapFree(GetProcessHeap(),0,pdwTagType);
if (dwErr is ERROR_INVALID_OPTION_TAG)
{
dwErr = ERROR_INVALID_SYNTAX; // show usage
}
return dwErr;
}
dwNumPref = dwNumArg;
ppm = HeapAlloc(GetProcessHeap(),
0,
dwNumPref * sizeof(PROTOCOL_METRIC));
if (ppm is NULL)
{
HeapFree(GetProcessHeap(),0,pdwTagType);
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY);
return ERROR_SUPPRESS_OUTPUT;
}
for ( i = 0, dwPrefIndex = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case 0:
{
//
// TAG = PROTOCOL
//
dwRes = MatchRoutingProtoTag(ppwcArguments[i + dwCurrentIndex]);
if (dwRes == (DWORD) -1)
{
DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
i = dwNumArg;
dwErr = ERROR_SUPPRESS_OUTPUT;
break;
}
ppm[dwPrefIndex++].dwProtocolId = dwRes;
break;
}
default :
{
i = dwNumArg;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
}
HeapFree(GetProcessHeap(), 0, pdwTagType);
switch(dwErr)
{
case NO_ERROR :
break;
default:
return dwErr;
}
if (dwPrefIndex)
{
//
// Add route pref
//
dwRes = AddDeleteRoutePrefLevel(ppm,
dwPrefIndex,
FALSE);
}
HeapFree(GetProcessHeap(), 0, ppm);
return dwErr;
}
DWORD
HandleIpSetRoutePref(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Gets options for setting route preferences
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
PROTOCOL_METRIC pm;
DWORD dwBitVector = 0, dwNumPref,dwPrefIndex;
DWORD dwErr = NO_ERROR,dwRes;
TAG_TYPE pttTags[] = {{TOKEN_PROTOCOL, TRUE,FALSE},
{TOKEN_PREF_LEVEL, TRUE,FALSE}};
PDWORD pdwTagType;
DWORD dwNumTags = 2, dwNumArg, i, dwAddr;
if (dwCurrentIndex >= dwArgCount)
{
//
// No arguments specified
//
return ERROR_SHOW_USAGE;
}
dwNumArg = dwArgCount - dwCurrentIndex;
pdwTagType = HeapAlloc(GetProcessHeap(),
0,
dwNumArg * sizeof(DWORD));
if (pdwTagType is NULL)
{
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY);
return ERROR_NOT_ENOUGH_MEMORY;
}
dwErr = MatchTagsInCmdLine(g_hModule, ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
dwNumTags,
pdwTagType);
if (dwErr isnot NO_ERROR)
{
HeapFree(GetProcessHeap(),0,pdwTagType);
if (dwErr is ERROR_INVALID_OPTION_TAG)
{
return ERROR_INVALID_SYNTAX; // show usage
}
return dwErr;
}
for ( i = 0, dwPrefIndex = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case 0: // PROTOCOL
dwRes = MatchRoutingProtoTag(ppwcArguments[i + dwCurrentIndex]);
if (dwRes == (DWORD) -1)
{
DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
i = dwNumArg;
dwErr = ERROR_SUPPRESS_OUTPUT;
break;
}
pm.dwProtocolId = dwRes;
//
// Get the metric too
//
if (pdwTagType[i+1] == 1)
{
pm.dwMetric =
wcstoul(ppwcArguments[i + 1 +dwCurrentIndex],NULL,10);
if (pm.dwMetric==0
&& wcscmp(ppwcArguments[i + 1 +dwCurrentIndex], L"0")!=0)
{
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
i++;
dwPrefIndex++;
}
else
{
dwErr = ERROR_INVALID_SYNTAX;
i = dwNumArg;
break;
}
break;
default :
i = dwNumArg;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
HeapFree(GetProcessHeap(), 0, pdwTagType);
switch(dwErr)
{
case NO_ERROR :
break;
default:
return dwErr;
}
dwErr = SetRoutePrefLevel(pm);
return dwErr;
}
DWORD
HandleIpSetLogLevel(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Gets options for setting global parameter namely logging level
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
DWORD dwErr = NO_ERROR;
TAG_TYPE pttTags[] = {{TOKEN_LOG_LEVEL,TRUE,FALSE}};
PDWORD pdwTagType;
DWORD dwNumTags = 1, dwNumArg, i, dwAddr;
DWORD dwLoggingLevel = (DWORD) -1;
BOOL bOkay = TRUE;
if (dwCurrentIndex >= dwArgCount)
{
//
// No arguments specified
//
return ERROR_SHOW_USAGE;
}
dwNumArg = dwArgCount - dwCurrentIndex;
pdwTagType = HeapAlloc(GetProcessHeap(),
0,
dwNumArg * sizeof(DWORD));
if (pdwTagType is NULL)
{
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY);
return ERROR_SUPPRESS_OUTPUT;
}
dwErr = MatchTagsInCmdLine(g_hModule, ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
dwNumTags,
pdwTagType);
if (dwErr isnot NO_ERROR)
{
HeapFree(GetProcessHeap(),0,pdwTagType);
if (dwErr is ERROR_INVALID_OPTION_TAG)
{
return ERROR_INVALID_SYNTAX;
}
return dwErr;
}
for ( i = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case 0: // LOGLEVEL
{
TOKEN_VALUE rgEnums[] =
{{TOKEN_VALUE_NONE, IPRTR_LOGGING_NONE},
{TOKEN_VALUE_ERROR, IPRTR_LOGGING_ERROR},
{TOKEN_VALUE_WARN, IPRTR_LOGGING_WARN},
{TOKEN_VALUE_INFO, IPRTR_LOGGING_INFO}};
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
rgEnums,
&dwLoggingLevel);
if (dwErr != NO_ERROR)
{
DispTokenErrMsg(g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
DisplayMessage( g_hModule,
MSG_IP_BAD_OPTION_ENUMERATION,
pttTags[pdwTagType[i]].pwszTag );
for (i=0; i<4; i++)
{
DisplayMessageT( L" %1!s!\n", rgEnums[i].pwszToken );
}
i = dwNumArg;
dwErr = ERROR_SUPPRESS_OUTPUT;
bOkay = FALSE;
break;
}
break;
}
default :
{
i = dwNumArg;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
}
HeapFree(GetProcessHeap(), 0, pdwTagType);
switch(dwErr)
{
case NO_ERROR :
break;
default:
return dwErr;
}
if (!bOkay)
{
return NO_ERROR;
}
dwErr = SetGlobalConfigInfo(dwLoggingLevel);
return dwErr;
}
DWORD
HandleIpSetIfFilter(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Gets options for setting interface filter parameters
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
DWORD dwNumParsed = 0;
DWORD dwErr = NO_ERROR,dwRes;
TAG_TYPE pttTags[] = {{TOKEN_NAME,TRUE,FALSE},
{TOKEN_FILTER_TYPE,FALSE,FALSE},
{TOKEN_ACTION,FALSE,FALSE},
{TOKEN_FRAGCHECK,FALSE,FALSE}};
PDWORD pdwTagType;
DWORD dwNumOpt;
DWORD dwNumTags = 4, dwNumArg, i, j;
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
DWORD dwFilterType, dwAction;
BOOL bFragCheck, bOkay = TRUE;
if (dwCurrentIndex >= dwArgCount)
{
//
// No arguments specified
//
return ERROR_SHOW_USAGE;
}
dwNumArg = dwArgCount - dwCurrentIndex;
pdwTagType = HeapAlloc(GetProcessHeap(),
0,
dwNumArg * sizeof(DWORD));
if (pdwTagType is NULL)
{
DisplayMessage(g_hModule, MSG_IP_NOT_ENOUGH_MEMORY);
return ERROR_SUPPRESS_OUTPUT;
}
dwErr = MatchTagsInCmdLine(g_hModule, ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
dwNumTags,
pdwTagType);
if (dwErr isnot NO_ERROR)
{
HeapFree(GetProcessHeap(),0,pdwTagType);
if (dwErr is ERROR_INVALID_OPTION_TAG)
{
return ERROR_INVALID_SYNTAX; // show usage
}
return dwErr;
}
for ( i = 0; i < dwNumArg; i++)
{
switch (pdwTagType[i])
{
case 0 :
{
DWORD BufLen = sizeof(wszIfName);
GetInterfaceName(ppwcArguments[i + dwCurrentIndex],
wszIfName,
BufLen,
&dwNumParsed);
// no filters allowed on INTERNAL/LOOPBACK interfaces
if (!_wcsicmp(wszIfName, L"internal") or
!_wcsicmp(wszIfName, L"loopback"))
{
DisplayMessage(g_hModule,
MSG_IP_BAD_INTERFACE_TYPE,
wszIfName);
dwErr = ERROR_SUPPRESS_OUTPUT;
i = dwNumArg;
}
break;
}
case 1:
{
TOKEN_VALUE rgEnums[] =
{{TOKEN_VALUE_INPUT, IP_IN_FILTER_INFO},
{TOKEN_VALUE_OUTPUT, IP_OUT_FILTER_INFO},
{TOKEN_VALUE_DIAL, IP_DEMAND_DIAL_FILTER_INFO}};
//
// Tag TYPE
//
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
rgEnums,
&dwFilterType);
if (dwErr != NO_ERROR)
{
DispTokenErrMsg(g_hModule, MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
DisplayMessage( g_hModule,
MSG_IP_BAD_OPTION_ENUMERATION,
pttTags[pdwTagType[i]].pwszTag );
for (i=0; i<sizeof(rgEnums)/sizeof(TOKEN_VALUE); i++)
{
DisplayMessageT( L" %1!s!\n", rgEnums[i].pwszToken );
}
i = dwNumArg;
bOkay = FALSE;
dwErr = ERROR_SUPPRESS_OUTPUT;
break;
}
break;
}
case 2:
{
TOKEN_VALUE rgEnums[] =
{{TOKEN_VALUE_DROP, PF_ACTION_DROP},
{TOKEN_VALUE_FORWARD, PF_ACTION_FORWARD}};
//
// Tag ACTION
//
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
rgEnums,
&dwAction);
if (dwErr != NO_ERROR)
{
DispTokenErrMsg(g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
DisplayMessage( g_hModule,
MSG_IP_BAD_OPTION_ENUMERATION,
pttTags[pdwTagType[i]].pwszTag );
for (i=0; i<sizeof(rgEnums)/sizeof(TOKEN_VALUE); i++)
{
DisplayMessageT( L" %1!s!\n", rgEnums[i].pwszToken );
}
i = dwNumArg;
dwErr = ERROR_SUPPRESS_OUTPUT;
bOkay = FALSE;
break;
}
break;
}
case 3:
{
TOKEN_VALUE rgEnums[] =
{{TOKEN_VALUE_ENABLE, TRUE},
{TOKEN_VALUE_DISABLE, FALSE}};
//
// TAG = FRAGCHK
//
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
rgEnums,
&dwRes);
if (dwErr != NO_ERROR)
{
DispTokenErrMsg(g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
DisplayMessage( g_hModule,
MSG_IP_BAD_OPTION_ENUMERATION,
pttTags[pdwTagType[i]].pwszTag );
for (i=0; i<sizeof(rgEnums)/sizeof(TOKEN_VALUE); i++)
{
DisplayMessageT( L" %1!s!\n", rgEnums[i].pwszToken );
}
i = dwNumArg;
dwErr = ERROR_SUPPRESS_OUTPUT;
bOkay = FALSE;
break;
}
bFragCheck = (dwRes) ? TRUE : FALSE;
break;
}
default:
{
i = dwNumArg;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
}
HeapFree(GetProcessHeap(), 0, pdwTagType);
switch(dwErr)
{
case NO_ERROR :
break;
default:
return dwErr;
}
if (!bOkay)
{
return NO_ERROR;
}
if (!pttTags[0].bPresent ||
(pttTags[1].bPresent && !pttTags[2].bPresent) ||
(!pttTags[1].bPresent && pttTags[2].bPresent))
{
return ERROR_INVALID_SYNTAX; // show usage
}
if (pttTags[3].bPresent)
{
dwErr = SetFragCheckInfo(wszIfName, bFragCheck);
}
if (dwErr isnot NO_ERROR)
{
return dwErr;
}
if (pttTags[1].bPresent)
{
dwErr = SetFilterInfo(wszIfName, dwFilterType, dwAction);
}
return dwErr;
}
DWORD
IpAddSetDelInterface(
PWCHAR *ppwcArguments,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwAction
)
/*++
Routine Description:
Gets options for setting interface parameters
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
DWORD dwBitVector = 0, dwNumParsed = 0;
DWORD dwErr = NO_ERROR, dwRes;
TAG_TYPE pttTags[] = {
{TOKEN_NAME, TRUE, FALSE},
{TOKEN_STATUS, FALSE,FALSE}};
BOOL bOkay = TRUE;
DWORD pdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD dwNumOpt;
DWORD dwStatus = IF_ADMIN_STATUS_UP;
DWORD dwNumTags = 2, dwNumArg, i, j;
WCHAR wszIfName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
DWORD dwMaxArgs = (dwAction is DELETE_COMMAND)? 1
: sizeof(pttTags)/sizeof(TAG_TYPE);
// Do generic processing
dwErr = PreHandleCommand( ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
1,
dwMaxArgs,
pdwTagType );
if (dwErr)
{
return dwErr;
}
dwNumArg = dwArgCount - dwCurrentIndex;
for (i=0; i<dwNumArg; i++)
{
switch (pdwTagType[i])
{
case 0: // NAME
{
DWORD BufLen = sizeof(wszIfName);
GetInterfaceName(ppwcArguments[i + dwCurrentIndex],
wszIfName,
BufLen,
&dwNumParsed);
break;
}
case 1: // STATE
{
TOKEN_VALUE rgEnums[] =
{{TOKEN_VALUE_ENABLE, IF_ADMIN_STATUS_UP},
{TOKEN_VALUE_DISABLE, IF_ADMIN_STATUS_DOWN}};
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
rgEnums,
&dwStatus);
if (dwErr isnot NO_ERROR)
{
DispTokenErrMsg(g_hModule,
MSG_IP_BAD_OPTION_VALUE,
pttTags[pdwTagType[i]].pwszTag,
ppwcArguments[i + dwCurrentIndex]);
DisplayMessage( g_hModule,
MSG_IP_BAD_OPTION_ENUMERATION,
pttTags[pdwTagType[i]].pwszTag );
for (i=0; i<sizeof(rgEnums)/sizeof(TOKEN_VALUE); i++)
{
DisplayMessageT( L" %1!s!\n", rgEnums[i].pwszToken );
}
i = dwNumArg;
dwErr = ERROR_SUPPRESS_OUTPUT;
bOkay = FALSE;
break;
}
break;
}
}
}
if (!bOkay)
{
return NO_ERROR;
}
if (dwAction is DELETE_COMMAND)
{
dwErr = DeleteInterfaceInfo(wszIfName);
if (dwErr isnot NO_ERROR)
{
return dwErr;
}
return ERROR_OKAY;
}
if (dwStatus is IF_ADMIN_STATUS_DOWN)
{
DWORD dwIfType;
// Make sure we support disabling this interface
dwErr = GetInterfaceInfo(wszIfName, NULL, NULL, &dwIfType);
if (dwErr == NO_ERROR)
{
if (dwIfType isnot ROUTER_IF_TYPE_DEDICATED)
{
DisplayMessage( g_hModule, MSG_IP_CANT_DISABLE_INTERFACE );
return ERROR_SUPPRESS_OUTPUT;
}
}
}
if (dwAction is ADD_COMMAND)
{
dwErr = AddInterfaceInfo(wszIfName);
}
dwErr = UpdateInterfaceStatusInfo(dwAction,
wszIfName,
dwStatus);
if (dwErr isnot NO_ERROR)
{
return dwErr;
}
return ERROR_OKAY;
}
DWORD
HandleIpAddInterface(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelInterface( ppwcArguments,
dwCurrentIndex,
dwArgCount,
ADD_COMMAND);
}
DWORD
HandleIpSetInterface(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelInterface( ppwcArguments,
dwCurrentIndex,
dwArgCount,
SET_COMMAND );
}
DWORD
HandleIpDelInterface(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return IpAddSetDelInterface( ppwcArguments,
dwCurrentIndex,
dwArgCount,
DELETE_COMMAND);
}
DWORD
HandleIpShowRoutePref(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
//
// No options expected
//
return ShowRoutePref(NULL);
}
DWORD
HandleIpShowLogLevel(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
//
// No options expected
//
if (dwCurrentIndex != dwArgCount)
{
return ERROR_SHOW_USAGE;
}
return ShowIpGlobal(NULL);
}
DWORD
HandleIpShowProtocol(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
//
// No options expected
//
return ShowIpProtocol();
}
DWORD
IpShowSingleInterfaceInfo(
IN LPCWSTR pwszInterfaceName,
IN DWORD dwInfoType,
IN DWORD dwFormat,
IN OUT PDWORD pdwNumRows
)
{
switch(dwInfoType)
{
case SHOW_IF_FILTER:
{
return ShowIpIfFilter(NULL, dwFormat, pwszInterfaceName, pdwNumRows);
}
case SHOW_INTERFACE:
{
return ShowIpInterface(dwFormat, pwszInterfaceName, pdwNumRows);
}
case SHOW_PERSISTENTROUTE:
{
return ShowIpPersistentRoute(NULL, pwszInterfaceName, pdwNumRows);
}
default:
{
return ERROR_INVALID_PARAMETER;
}
}
}
DWORD
IpShowInterfaceInfo(
PWCHAR *ppwcArguments,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwInfoType
)
/*++
Routine Description:
Gets options for showing various interface information
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
dwInfoType - The type of info to display
Return Value:
NO_ERROR
--*/
{
DWORD dwErr, dwTotal;
TAG_TYPE pttTags[] = {{TOKEN_NAME,FALSE,FALSE}};
WCHAR wszInterfaceName[MAX_INTERFACE_NAME_LEN + 1] = L"\0";
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD dwCount, i, j, dwNumOpt;
DWORD dwNumTags = 1, dwNumArg, dwNumParsed;
DWORD dwSize, dwRes, dwNumRows = 0;
PMPR_INTERFACE_0 pmi0;
// Do generic processing
dwErr = PreHandleCommand( ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
1,
rgdwTagType );
if (dwErr isnot NO_ERROR)
{
return dwErr;
}
// If interface specified, show info for specified interface only.
for (i=0; i<dwArgCount-dwCurrentIndex; i++)
{
switch (rgdwTagType[i])
{
case 0: // NAME
{
DWORD BufLen = sizeof(wszInterfaceName);
GetInterfaceName( ppwcArguments[i + dwCurrentIndex],
wszInterfaceName,
BufLen,
&dwNumParsed);
dwErr = IpShowSingleInterfaceInfo(wszInterfaceName,
dwInfoType,
FORMAT_VERBOSE,
&dwNumRows);
if (!dwNumRows)
{
DisplayMessage( g_hModule, MSG_IP_NO_ENTRIES );
dwErr = ERROR_SUPPRESS_OUTPUT;
}
return dwErr;
}
}
}
// No Interface specified. Enumerate interfaces and show
// info for each interface.
dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0, &dwCount, &dwTotal);
if (dwErr isnot NO_ERROR)
{
return dwErr;
}
for (i=0; i<dwCount && dwErr is NO_ERROR; i++)
{
dwErr = IpShowSingleInterfaceInfo( pmi0[i].wszInterfaceName,
dwInfoType,
FORMAT_TABLE,
&dwNumRows );
if (dwErr is ERROR_NO_SUCH_INTERFACE)
{
dwErr = NO_ERROR;
}
}
if (!dwNumRows)
{
DisplayMessage( g_hModule, MSG_IP_NO_ENTRIES );
}
return dwErr;
}
DWORD
HandleIpShowIfFilter(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
return IpShowInterfaceInfo(ppwcArguments,
dwCurrentIndex,
dwArgCount,
SHOW_IF_FILTER);
}
DWORD
HandleIpShowInterface(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
return IpShowInterfaceInfo(ppwcArguments,
dwCurrentIndex,
dwArgCount,
SHOW_INTERFACE);
}
DWORD
HandleIpShowPersistentRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Handler for show ip route. We just call the main interface info display
handler
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
DisplayMessage(g_hModule, MSG_IP_PERSISTENT_CONFIG);
return IpShowInterfaceInfo(ppwcArguments,
dwCurrentIndex,
dwArgCount,
SHOW_PERSISTENTROUTE);
}
#ifdef KSL_IPINIP
DWORD
HandleIpAddIpIpTunnel(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
return IpAddSetIpIpTunnel(ppwcArguments,
dwCurrentIndex,
dwArgCount,
TRUE);
}
DWORD
HandleIpSetIpIpTunnel(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
/*++
Routine Description:
Arguments:
ppwcArguments - Argument array
dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
Return Value:
NO_ERROR
--*/
{
return IpAddSetIpIpTunnel(ppwcArguments,
dwCurrentIndex,
dwArgCount,
FALSE);
}
DWORD
IpAddSetIpIpTunnel(
PWCHAR *ppwcArguments,
DWORD dwCurrentIndex,
DWORD dwArgCount,
BOOL bAdd
)
{
DWORD dwNumArgs, dwErr, dwNumParsed;
TAG_TYPE rgTags[] = {{TOKEN_NAME, TRUE, FALSE},
{TOKEN_LOCALADDR, TRUE, FALSE},
{TOKEN_REMADDR, TRUE, FALSE},
{TOKEN_TTL, FALSE,FALSE}};
WCHAR rgwcIfName[MAX_INTERFACE_NAME_LEN + 1];
DWORD rgdwTagType[sizeof(rgTags)/sizeof(TAG_TYPE)];
ULONG i;
PWCHAR pwszIfName;
IPINIP_CONFIG_INFO ConfigInfo;
dwNumArgs = dwArgCount - dwCurrentIndex;
if((dwCurrentIndex > dwArgCount) or
(dwNumArgs isnot 4))
{
//
// No arguments specified
//
return ERROR_SHOW_USAGE;
}
dwErr = MatchTagsInCmdLine(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
rgTags,
sizeof(rgTags)/sizeof(TAG_TYPE),
rgdwTagType);
if (dwErr isnot NO_ERROR)
{
if (dwErr is ERROR_INVALID_OPTION_TAG)
{
return ERROR_INVALID_SYNTAX;
}
return dwErr;
}
for(i = 0; i < dwNumArgs; i ++)
{
switch (rgdwTagType[i])
{
case 0 : // NAME
{
DWORD BufLen = sizeof(rgwcIfName);
dwErr = GetInterfaceName(ppwcArguments[i + dwCurrentIndex],
rgwcIfName,
BufLen,
&dwNumParsed);
if(bAdd)
{
if(dwErr is NO_ERROR)
{
return ERROR_OBJECT_ALREADY_EXISTS;
}
pwszIfName = ppwcArguments[i + dwCurrentIndex];
}
else
{
if(dwErr isnot NO_ERROR)
{
return dwErr;
}
pwszIfName = rgwcIfName;
}
break;
}
case 1:
{
//
// Tag for localaddr
//
dwErr = GetIpAddress(ppwcArguments[i + dwCurrentIndex],
&ConfigInfo.dwLocalAddress);
break;
}
case 2:
{
//
// Tag for remoteaddr
//
dwErr = GetIpAddress(ppwcArguments[i + dwCurrentIndex],
&ConfigInfo.dwRemoteAddress);
break;
}
case 3:
{
//
// Tag for ttl
//
ConfigInfo.byTtl =
LOBYTE(LOWORD(wcstoul(ppwcArguments[i + dwCurrentIndex],
NULL,
10)));
break;
}
default:
{
i = dwNumArgs;
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
}
switch(dwErr)
{
case NO_ERROR:
{
break;
}
default:
{
return dwErr;
}
}
for(i = 0; i < dwNumArgs; i++)
{
if(!rgTags[i].bPresent)
{
DisplayMessage(g_hModule,
MSG_CANT_FIND_EOPT);
return ERROR_INVALID_SYNTAX;
}
}
dwErr = AddSetIpIpTunnelInfo(pwszIfName,
&ConfigInfo);
return dwErr;
}
#endif //KSL_IPINIP
DWORD
IpDump(
IN LPCWSTR pwszRouter,
IN LPWSTR *ppwcArguments,
IN DWORD dwArgCount,
IN LPCVOID pvData
)
{
DumpIpInformation((HANDLE)-1);
return NO_ERROR;
}
#if 0
DWORD
HandleIpInstall(
PWCHAR pwszMachine,
PWCHAR *ppwcArguments,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwFlags,
PVOID pvData,
BOOL *pbDone
)
{
// XXX DLLPath, ProtocolId
// XXX set default info here
// global info block (what is this?)
// protocol priority block (no need?)
// multicast boundaries block (no need)
return NO_ERROR;
}
DWORD
HandleIpUninstall(
PWCHAR pwszMachine,
PWCHAR *ppwcArguments,
DWORD dwCurrentIndex,
DWORD dwArgCount,
DWORD dwFlags,
PVOID pvData,
BOOL *pbDone
)
{
PMPR_INTERFACE_0 pmi0;
DWORD dwCount, dwTotal, i, dwErr;
// Remove global info
// XXX
// Remove interface info
dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0, &dwCount, &dwTotal);
if (dwErr is NO_ERROR)
{
for (i=0; i<dwCount; i++)
{
DeleteInterfaceInfo(pmi0[i].wszInterfaceName);
}
}
return NO_ERROR;
}
#endif
DWORD
HandleIpReset(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
PMPR_INTERFACE_0 pmi0;
DWORD dwCount, dwTotal, i, dwErr, dwSize, dwBlkSize;
DWORD dwNumProtocols;
GLOBAL_INFO gi;
PPRIORITY_INFO pPriInfo;
PPROTOCOL_METRIC pProtocolMetrics;
RTR_INFO_BLOCK_HEADER *pInfoHdr;
RTR_INFO_BLOCK_HEADER *pLocalInfoHdr;
PROTOCOL_METRIC defaultProtocolMetrics[] =
{
{PROTO_IP_LOCAL, 1},
{PROTO_IP_NT_STATIC, 3},
{PROTO_IP_NT_STATIC_NON_DOD, 5},
{PROTO_IP_NT_AUTOSTATIC, 7},
{PROTO_IP_NETMGMT, 10},
{PROTO_IP_OSPF, 110},
{PROTO_IP_RIP, 120}
};
PROTOCOL_METRIC defaultProtocolMetricsNT4[] =
{
{PROTO_IP_LOCAL, 1},
{PROTO_IP_NETMGMT, 2},
{PROTO_IP_OSPF, 3},
{PROTO_IP_RIP, 4},
{PROTO_IP_IGMP, 5}
};
// delete all blocks except the IP_GLOBAL_INFO
dwErr = ValidateGlobalInfo(&pInfoHdr);
if (dwErr is NO_ERROR)
{
// Copy to a local buffer just in case the APIs modify it as we go
dwSize = sizeof(RTR_INFO_BLOCK_HEADER) * pInfoHdr->TocEntriesCount;
pLocalInfoHdr = MALLOC(dwSize);
if (pLocalInfoHdr is NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
memcpy(pLocalInfoHdr, pInfoHdr, dwSize);
// Set Global and RoutePref info
{
dwBlkSize = sizeof(GLOBAL_INFO);
dwCount = 1;
gi.bFilteringOn = FALSE;
gi.dwLoggingLevel = IPRTR_LOGGING_ERROR;
dwErr = IpmontrSetInfoBlockInGlobalInfo(IP_GLOBAL_INFO,
(PBYTE) &gi,
dwBlkSize,
dwCount);
}
{
// Based on the router version, calculate the number
// of protocols etc.
// TODO: currently assuming >=NT5. Should find out the router
// version somehow
dwNumProtocols =
sizeof(defaultProtocolMetrics)/sizeof(PROTOCOL_METRIC);
pProtocolMetrics = defaultProtocolMetrics;
dwBlkSize = SIZEOF_PRIORITY_INFO(dwNumProtocols);
dwCount = 1;
// Allocate buffer to hold the Priority Information
pPriInfo = MALLOC(dwBlkSize);
if (pPriInfo is NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
pPriInfo->dwNumProtocols = dwNumProtocols;
memcpy(
pPriInfo->ppmProtocolMetric,
pProtocolMetrics,
dwNumProtocols * sizeof(PROTOCOL_METRIC));
dwErr = IpmontrSetInfoBlockInGlobalInfo(IP_PROT_PRIORITY_INFO,
(PBYTE) pPriInfo,
dwBlkSize,
dwCount);
FREE(pPriInfo);
}
for (i=0; i<pLocalInfoHdr->TocEntriesCount; i++)
{
switch (pLocalInfoHdr->TocEntry[i].InfoType)
{
case IP_GLOBAL_INFO:
case IP_PROT_PRIORITY_INFO:
// already done
break;
default:
IpmontrDeleteInfoBlockFromGlobalInfo(
pLocalInfoHdr->TocEntry[i].InfoType );
break;
}
}
FREE(pLocalInfoHdr);
}
// Delete all interface info
dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0, &dwCount, &dwTotal);
if (dwErr is NO_ERROR)
{
for (i=0; i<dwCount; i++)
{
DeleteInterfaceInfo(pmi0[i].wszInterfaceName);
}
}
return NO_ERROR;
}