Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

3039 lines
93 KiB

//=============================================================================
// Copyright (c) 2001 Microsoft Corporation
// Abstract:
// This module implements IPv6 configuration commands.
//=============================================================================
#include "precomp.h"
#pragma hdrstop
typedef enum {
ACTION_ADD,
ACTION_SET
} ACTION;
DWORD
GetTime(
IN PWCHAR pwszLife)
{
PWCHAR pwcUnit;
DWORD dwUnits, dwLife = 0;
if (!_wcsnicmp(pwszLife, TOKEN_VALUE_INFINITE, wcslen(pwszLife))) {
return INFINITE_LIFETIME;
}
while ((pwcUnit = wcspbrk(pwszLife, L"sSmMhHdD")) != NULL) {
switch (*pwcUnit) {
case L's':
case L'S':
dwUnits = SECONDS;
break;
case L'm':
case L'M':
dwUnits = MINUTES;
break;
case L'h':
case L'H':
dwUnits = HOURS;
break;
case L'd':
case L'D':
dwUnits = DAYS;
break;
}
*pwcUnit = L'\0';
dwLife += wcstoul(pwszLife, NULL, 10) * dwUnits;
pwszLife = pwcUnit + 1;
if (*pwszLife == L'\0')
return dwLife;
}
return dwLife + wcstoul(pwszLife, NULL, 10);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to addresses
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleAddSetAddress(
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN ACTION Action,
OUT BOOL *pbDone
)
{
DWORD dwErr, i;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
{TOKEN_ADDRESS, TRUE, FALSE},
{TOKEN_TYPE, FALSE, FALSE},
{TOKEN_VALIDLIFETIME, FALSE, FALSE},
{TOKEN_PREFERREDLIFETIME, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
IN6_ADDR ipAddress;
TOKEN_VALUE rgtvTypeEnum[] = {{ TOKEN_VALUE_UNICAST, ADE_UNICAST },
{ TOKEN_VALUE_ANYCAST, ADE_ANYCAST }};
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD dwType = ADE_UNICAST;
DWORD dwValidLifetime = INFINITE_LIFETIME;
DWORD dwPreferredLifetime = INFINITE_LIFETIME;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // ADDRESS
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipAddress);
break;
case 2: // TYPE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvTypeEnum),
rgtvTypeEnum,
&dwType);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 3: // VALIDLIFETIME
dwValidLifetime = GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 4: // PREFERREDLIFETIME
dwPreferredLifetime = GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 5: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return UpdateAddress(pwszIfFriendlyName, &ipAddress, dwType,
dwValidLifetime, dwPreferredLifetime, bPersistent);
}
DWORD
HandleAddAddress(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return HandleAddSetAddress(ppwcArguments, dwCurrentIndex, dwArgCount,
ACTION_ADD, pbDone);
}
DWORD
HandleSetAddress(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return HandleAddSetAddress(ppwcArguments, dwCurrentIndex, dwArgCount,
ACTION_SET, pbDone);
}
DWORD
HandleDelAddress(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr, i;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
{TOKEN_ADDRESS, TRUE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
IN6_ADDR ipAddress;
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD dwType = ADE_UNICAST;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // ADDRESS
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipAddress);
break;
case 2: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return UpdateAddress(pwszIfFriendlyName, &ipAddress, dwType,
0, 0, bPersistent);
}
DWORD
HandleShowAddress(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
{TOKEN_LEVEL, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
DWORD i;
BOOL bPersistent = FALSE;
FORMAT Format = FORMAT_NORMAL;
TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
{ TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
Format = FORMAT_VERBOSE;
break;
case 1: // LEVEL
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
rgtvLevelEnum,
(DWORD*)&Format);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 2: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryAddressTable(pwszIfFriendlyName, Format, bPersistent);
}
DWORD
HandleShowJoins(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
{TOKEN_LEVEL, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
DWORD i;
FORMAT Format = FORMAT_NORMAL;
TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
{ TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // LEVEL
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
rgtvLevelEnum,
(DWORD*)&Format);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryMulticastAddressTable(pwszIfFriendlyName, Format);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to mobility
/////////////////////////////////////////////////////////////////////////////
TOKEN_VALUE rgtvSecurityEnum[] = {
{ TOKEN_VALUE_ENABLED, TRUE },
{ TOKEN_VALUE_DISABLED, FALSE },
};
DWORD
HandleSetMobility(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_SECURITY, FALSE, FALSE},
{TOKEN_BINDINGCACHELIMIT, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD i, dwEnableSecurity = -1, dwBindingCacheLimit = -1;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
1,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // SECURITY
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvSecurityEnum),
rgtvSecurityEnum,
&dwEnableSecurity);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 1: // BINDINGCACHELIMIT
dwBindingCacheLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
NULL, 10);
break;
case 2: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return UpdateMobilityParameters(dwEnableSecurity, dwBindingCacheLimit,
bPersistent);
}
DWORD
HandleShowMobility(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i;
BOOL bPersistent = FALSE;
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryMobilityParameters(FORMAT_NORMAL, bPersistent);
}
DWORD
HandleShowBindingCacheEntries(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return QueryBindingCache();
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to other global parameters
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleSetGlobal(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr, i;
TAG_TYPE pttTags[] = {{TOKEN_DEFAULTCURHOPLIMIT, FALSE, FALSE},
{TOKEN_NEIGHBORCACHELIMIT, FALSE, FALSE},
{TOKEN_DESTINATIONCACHELIMIT, FALSE, FALSE},
{TOKEN_REASSEMBLYLIMIT, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD dwDefaultCurHopLimit = -1;
DWORD dwNeighborCacheLimit = -1;
DWORD dwRouteCacheLimit = -1;
DWORD dwReassemblyLimit = -1;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
1,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // DEFAULTCURHOPLIMIT
dwDefaultCurHopLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
NULL, 10);
break;
case 1: // NEIGHBORCACHELIMIT
dwNeighborCacheLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
NULL, 10);
break;
case 2: // DESTINATIONCACHELIMIT
dwRouteCacheLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
NULL, 10);
break;
case 3: // REASSEMBLYLIMIT
dwReassemblyLimit = wcstoul(ppwcArguments[dwCurrentIndex + i],
NULL, 10);
break;
case 4: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return UpdateGlobalParameters(dwDefaultCurHopLimit, dwNeighborCacheLimit,
dwRouteCacheLimit, dwReassemblyLimit,
bPersistent);
}
DWORD
HandleShowGlobal(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i;
BOOL bPersistent = FALSE;
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryGlobalParameters(FORMAT_NORMAL, bPersistent);
}
DWORD
HandleSetPrivacy(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr, i;
TAG_TYPE pttTags[] = {{TOKEN_STATE, FALSE, FALSE},
{TOKEN_MAXDADATTEMPTS, FALSE, FALSE},
{TOKEN_MAXVALIDLIFETIME, FALSE, FALSE},
{TOKEN_MAXPREFERREDLIFETIME, FALSE, FALSE},
{TOKEN_REGENERATETIME, FALSE, FALSE},
{TOKEN_MAXRANDOMTIME, FALSE, FALSE},
{TOKEN_RANDOMTIME, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvStateEnum[] = {{ TOKEN_VALUE_DISABLED, USE_ANON_NO },
{ TOKEN_VALUE_ENABLED, USE_ANON_YES }};
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD dwState = -1;
DWORD dwMaxDadAttempts = -1;
DWORD dwMaxValidLifetime = -1;
DWORD dwMaxPrefLifetime = -1;
DWORD dwRegenerateTime = -1;
DWORD dwMaxRandomTime = -1;
DWORD dwRandomTime = -1;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
1,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // STATE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStateEnum),
rgtvStateEnum,
&dwState);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 1: // MAXDADATTEMPTS
dwMaxDadAttempts = wcstoul(ppwcArguments[dwCurrentIndex + i],
NULL, 10);
break;
case 2: // MAXVALIDLIFETIME
dwMaxValidLifetime =
GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 3: // MAXPREFLIFETIME
dwMaxPrefLifetime =
GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 4: // REGENERATETIME
dwRegenerateTime =
GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 5: // MAXRANDOMTIME
dwMaxRandomTime =
GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 6: // RANDOMTIME
dwRandomTime =
GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 7: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return UpdatePrivacyParameters(dwState, dwMaxDadAttempts,
dwMaxValidLifetime, dwMaxPrefLifetime,
dwRegenerateTime, dwMaxRandomTime,
dwRandomTime, bPersistent);
}
DWORD
HandleShowPrivacy(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i;
BOOL bPersistent = FALSE;
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryPrivacyParameters(FORMAT_NORMAL, bPersistent);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to interfaces
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleAddV6V4Tunnel(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
{TOKEN_LOCALADDRESS, TRUE, FALSE},
{TOKEN_REMOTEADDRESS, TRUE, FALSE},
{TOKEN_NEIGHBORDISCOVERY, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i, dwNeighborDiscovery = FALSE;
IN_ADDR ipLocalAddr, ipRemoteAddr;
PWCHAR pwszFriendlyName;
TOKEN_VALUE rgtvNDEnum[] = {{ TOKEN_VALUE_DISABLED, FALSE },
{ TOKEN_VALUE_ENABLED, TRUE }};
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // LOCALADDRESS
dwErr = GetIpv4Address(ppwcArguments[i + dwCurrentIndex],
&ipLocalAddr);
break;
case 2: // REMOTEADDRESS
dwErr = GetIpv4Address(ppwcArguments[i + dwCurrentIndex],
&ipRemoteAddr);
break;
case 3: // NEIGHBORDISCOVERY
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvNDEnum),
rgtvNDEnum,
&dwNeighborDiscovery);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 4: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
dwErr = AddTunnelInterface(pwszFriendlyName, &ipLocalAddr, &ipRemoteAddr,
IPV6_IF_TYPE_TUNNEL_V6V4, dwNeighborDiscovery,
bPersistent);
if (dwErr == ERROR_INVALID_HANDLE) {
DisplayMessage(g_hModule, EMSG_INVALID_ADDRESS);
dwErr = ERROR_SUPPRESS_OUTPUT;
}
return dwErr;
}
DWORD
HandleAdd6over4Tunnel(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
{TOKEN_LOCALADDRESS, TRUE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD i, dwEnableSecurity;
PWCHAR pwszFriendlyName;
IN_ADDR ipLocalAddr;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // LOCALADDRESS
dwErr = GetIpv4Address(ppwcArguments[i + dwCurrentIndex],
&ipLocalAddr);
break;
case 2: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
dwErr = AddTunnelInterface(pwszFriendlyName, &ipLocalAddr, NULL,
IPV6_IF_TYPE_TUNNEL_6OVER4,
TRUE,
bPersistent);
if (dwErr == ERROR_INVALID_HANDLE) {
DisplayMessage(g_hModule, EMSG_INVALID_ADDRESS);
dwErr = ERROR_SUPPRESS_OUTPUT;
}
return dwErr;
}
DWORD
HandleSetInterface(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
{TOKEN_FORWARDING, FALSE, FALSE},
{TOKEN_ADVERTISE, FALSE, FALSE},
{TOKEN_MTU, FALSE, FALSE},
{TOKEN_SITEID, FALSE, FALSE},
{TOKEN_METRIC, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvEnum[] = {{ TOKEN_VALUE_DISABLED, FALSE },
{ TOKEN_VALUE_ENABLED, TRUE }};
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
PWCHAR pwszIfFriendlyName = NULL;
DWORD i, dwMtu = 0, dwSiteId = 0, dwMetric = -1;
DWORD dwAdvertise = -1, dwForwarding = -1;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // FORWARDING
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvEnum),
rgtvEnum,
&dwForwarding);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 2: // ADVERTISE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvEnum),
rgtvEnum,
&dwAdvertise);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 3: // MTU
dwMtu = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
case 4: // SITEID
dwSiteId = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
case 5: // METRIC
dwMetric = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
case 6: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return UpdateInterface(pwszIfFriendlyName, dwForwarding, dwAdvertise,
dwMtu, dwSiteId, dwMetric, bPersistent);
}
DWORD
HandleDelInterface(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, TRUE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD i;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return DeleteInterface(pwszIfFriendlyName, bPersistent);
}
DWORD
HandleShowInterface(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
{TOKEN_LEVEL, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
DWORD i;
FORMAT Format = FORMAT_NORMAL;
TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
{ TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
BOOL bPersistent = FALSE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
Format = FORMAT_VERBOSE;
break;
case 1: // LEVEL
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
rgtvLevelEnum,
(DWORD*)&Format);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 2: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryInterface(pwszIfFriendlyName, Format, bPersistent);
}
DWORD
HandleRenew(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
DWORD i;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return RenewInterface(pwszIfFriendlyName);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to the neighbor cache
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleDelNeighbors(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
{TOKEN_ADDRESS, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
DWORD i;
IN6_ADDR ipAddress, *pipAddress = NULL;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // ADDRESS
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipAddress);
pipAddress = &ipAddress;
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return FlushNeighborCache(pwszIfFriendlyName, pipAddress);
}
DWORD
HandleShowNeighbors(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
{TOKEN_ADDRESS, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
DWORD i;
IN6_ADDR ipAddress, *pipAddress = NULL;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // ADDRESS
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipAddress);
pipAddress = &ipAddress;
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryNeighborCache(pwszIfFriendlyName, pipAddress);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to the prefix policies
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleAddSetPrefixPolicy(
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN ACTION Action,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_PREFIX, TRUE, FALSE},
{TOKEN_PRECEDENCE, TRUE, FALSE},
{TOKEN_LABEL, TRUE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD i, dwPrefixLength, dwPrecedence = -1, dwLabel = -1;
IN6_ADDR ipAddress;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // PREFIX
dwErr = GetIpv6Prefix(ppwcArguments[i + dwCurrentIndex],
&ipAddress, &dwPrefixLength);
break;
case 1: // PRECEDENCE
dwPrecedence = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
case 2: // LABEL
dwLabel = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
case 3: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return UpdatePrefixPolicy(&ipAddress, dwPrefixLength, dwPrecedence,
dwLabel, bPersistent);
}
DWORD
HandleAddPrefixPolicy(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return HandleAddSetPrefixPolicy(ppwcArguments, dwCurrentIndex, dwArgCount,
ACTION_ADD, pbDone);
}
DWORD
HandleSetPrefixPolicy(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return HandleAddSetPrefixPolicy(ppwcArguments, dwCurrentIndex, dwArgCount,
ACTION_SET, pbDone);
}
DWORD
HandleDelPrefixPolicy(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_PREFIX, TRUE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD i, dwPrefixLength;
IN6_ADDR ipAddress;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // PREFIX
dwErr = GetIpv6Prefix(ppwcArguments[i + dwCurrentIndex],
&ipAddress, &dwPrefixLength);
break;
case 1: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return DeletePrefixPolicy(&ipAddress, dwPrefixLength, bPersistent);
}
DWORD
HandleShowPrefixPolicy(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i;
BOOL bPersistent = FALSE;
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryPrefixPolicy(FORMAT_NORMAL, bPersistent);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to routes
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleAddSetRoute(
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN ACTION Action,
OUT BOOL *pbDone
)
{
DWORD dwErr, i;
TAG_TYPE pttTags[] = {{TOKEN_PREFIX, TRUE, FALSE},
{TOKEN_INTERFACE, TRUE, FALSE},
{TOKEN_NEXTHOP, FALSE, FALSE},
{TOKEN_SITEPREFIXLENGTH, FALSE, FALSE},
{TOKEN_METRIC, FALSE, FALSE},
{TOKEN_PUBLISH, FALSE, FALSE},
{TOKEN_VALIDLIFETIME, FALSE, FALSE},
{TOKEN_PREFERREDLIFETIME, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvPublishEnum[] = {
{TOKEN_VALUE_NO, PUBLISH_NO },
{TOKEN_VALUE_AGE, PUBLISH_AGE },
{TOKEN_VALUE_YES, PUBLISH_IMMORTAL }};
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD dwPrefixLength, dwMetric = ROUTE_PREF_HIGHEST;
DWORD dwSitePrefixLength = 0;
IN6_ADDR ipPrefix, ipNextHop, *pipNextHop = NULL;
PWCHAR pwszIfFriendlyName;
PUBLISH Publish = PUBLISH_NO;
DWORD dwValidLifetime = INFINITE_LIFETIME;
DWORD dwPreferredLifetime = INFINITE_LIFETIME;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // PREFIX
dwErr = GetIpv6Prefix(ppwcArguments[i + dwCurrentIndex],
&ipPrefix, &dwPrefixLength);
break;
case 1: // INTERFACE
pwszIfFriendlyName = ppwcArguments[dwCurrentIndex + i];
break;
case 2: // NEXTHOP
pipNextHop = &ipNextHop;
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipNextHop);
break;
case 3: // SITEPREFIXLENGTH
dwSitePrefixLength = wcstoul(ppwcArguments[dwCurrentIndex + i],
NULL, 10);
break;
case 4: // METRIC
dwMetric = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
case 5: // PUBLISH
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvPublishEnum),
rgtvPublishEnum,
(DWORD*)&Publish);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 6: // VALIDLIFETIME
dwValidLifetime = GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 7: // PREFERREDLIFETIME
dwPreferredLifetime = GetTime(ppwcArguments[dwCurrentIndex + i]);
break;
case 8: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
if ((dwPreferredLifetime == INFINITE_LIFETIME) &&
(dwValidLifetime != INFINITE_LIFETIME)) {
dwPreferredLifetime = dwValidLifetime;
}
// Disallow persistent aging routes with non-infinite valid lifetimes,
// since every reboot they would come back, and then go away after
// the lifetime expires. This would be very confusing, and so we
// just disallow it.
if ((Publish != PUBLISH_IMMORTAL) &&
(dwValidLifetime != INFINITE_LIFETIME) &&
(bPersistent == TRUE)) {
return ERROR_INVALID_PARAMETER;
// DisplayMessage(g_hModule, EMSG_CANT_PERSIST_AGING_ROUTES);
// return ERROR_SUPPRESS_OUTPUT;
}
return UpdateRouteTable(&ipPrefix, dwPrefixLength, pwszIfFriendlyName,
pipNextHop, dwMetric, Publish, dwSitePrefixLength,
dwValidLifetime, dwPreferredLifetime, bPersistent);
}
DWORD
HandleAddRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return HandleAddSetRoute(ppwcArguments, dwCurrentIndex, dwArgCount,
ACTION_ADD, pbDone);
}
DWORD
HandleSetRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return HandleAddSetRoute(ppwcArguments, dwCurrentIndex, dwArgCount,
ACTION_SET, pbDone);
}
DWORD
HandleDelRoute(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr, i;
TAG_TYPE pttTags[] = {{TOKEN_PREFIX, TRUE, FALSE},
{TOKEN_INTERFACE, TRUE, FALSE},
{TOKEN_NEXTHOP, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
DWORD dwPrefixLength, dwMetric = ROUTE_PREF_HIGHEST;
DWORD dwSitePrefixLength = 0;
IN6_ADDR ipPrefix, ipNextHop, *pipNextHop = NULL;
PWCHAR pwszIfFriendlyName;
PUBLISH Publish = PUBLISH_NO;
BOOL bPersistent = TRUE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // PREFIX
dwErr = GetIpv6Prefix(ppwcArguments[i + dwCurrentIndex],
&ipPrefix, &dwPrefixLength);
break;
case 1: // INTERFACE
pwszIfFriendlyName = ppwcArguments[dwCurrentIndex + i];
break;
case 2: // NEXTHOP
pipNextHop = &ipNextHop;
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipNextHop);
break;
case 3: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return UpdateRouteTable(&ipPrefix, dwPrefixLength, pwszIfFriendlyName,
pipNextHop, dwMetric, Publish, dwSitePrefixLength,
0, 0, bPersistent);
}
DWORD
HandleShowRoutes(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_LEVEL, FALSE, FALSE},
{TOKEN_STORE, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i;
IN6_ADDR ipAddress, *pipAddress = NULL;
TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
{ TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
TOKEN_VALUE rgtvStoreEnum[] = {{ TOKEN_VALUE_ACTIVE, FALSE },
{ TOKEN_VALUE_PERSISTENT, TRUE }};
FORMAT Format = FORMAT_NORMAL;
BOOL bPersistent = FALSE;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // LEVEL
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
rgtvLevelEnum,
(DWORD*)&Format);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
case 1: // STORE
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvStoreEnum),
rgtvStoreEnum,
&bPersistent);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryRouteTable(Format, bPersistent);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to the destination cache
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleDelDestinationCache(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
{TOKEN_ADDRESS, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
DWORD i;
IN6_ADDR ipAddress, *pipAddress = NULL;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // ADDRESS
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipAddress);
pipAddress = &ipAddress;
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return FlushRouteCache(pwszIfFriendlyName, pipAddress);
}
DWORD
HandleShowDestinationCache(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, FALSE, FALSE},
{TOKEN_ADDRESS, FALSE, FALSE},
{TOKEN_LEVEL, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
PWCHAR pwszIfFriendlyName = NULL;
DWORD i;
IN6_ADDR ipAddress, *pipAddress = NULL;
FORMAT Format = FORMAT_NORMAL;
TOKEN_VALUE rgtvLevelEnum[] = {{ TOKEN_VALUE_NORMAL, FORMAT_NORMAL },
{ TOKEN_VALUE_VERBOSE, FORMAT_VERBOSE }};
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
for (i=0; (dwErr == NO_ERROR) && (i<dwArgCount-dwCurrentIndex); i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // ADDRESS
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipAddress);
pipAddress = &ipAddress;
Format = FORMAT_VERBOSE;
break;
case 2: // LEVEL
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvLevelEnum),
rgtvLevelEnum,
(DWORD*)&Format);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
// Now do the work
return QueryRouteCache(pwszIfFriendlyName, pipAddress, Format);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to the site prefix table
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleShowSitePrefixes(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return QuerySitePrefixTable(FORMAT_NORMAL);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to installation
/////////////////////////////////////////////////////////////////////////////
DWORD
HandleInstall(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return AddOrRemoveIpv6(TRUE);
}
DWORD
HandleReset(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr;
#if TEREDO
dwErr = ResetTeredo();
if (dwErr != NO_ERROR) {
return dwErr;
}
#endif // TEREDO
return ResetIpv6Config(TRUE);
}
DWORD
HandleUninstall(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return AddOrRemoveIpv6(FALSE);
}
/////////////////////////////////////////////////////////////////////////////
// Commands related to deprecated functionality
/////////////////////////////////////////////////////////////////////////////
#define KEY_ENABLE_6OVER4 L"Enable6over4"
#define KEY_ENABLE_V4COMPAT L"EnableV4Compat"
#define BM_ENABLE_6OVER4 0x01
#define BM_ENABLE_V4COMPAT 0x02
DWORD
HandleSetState(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr = NO_ERROR;
HKEY hGlobal;
STATE stEnable6over4;
STATE stEnableV4Compat;
DWORD dwBitVector = 0;
TAG_TYPE pttTags[] = {{TOKEN_6OVER4, FALSE, FALSE},
{TOKEN_V4COMPAT, FALSE, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD dwNumArg;
DWORD i;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
1,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
if (dwErr isnot NO_ERROR) {
return dwErr;
}
for (i=0; i<dwArgCount-dwCurrentIndex; i++) {
switch(rgdwTagType[i]) {
case 0: // 6OVER4
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvEnums),
rgtvEnums,
(PDWORD)&stEnable6over4);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwBitVector |= BM_ENABLE_6OVER4;
break;
case 1: // V4COMPAT
dwErr = MatchEnumTag(NULL,
ppwcArguments[dwCurrentIndex + i],
NUM_TOKENS_IN_TABLE(rgtvEnums),
rgtvEnums,
(PDWORD)&stEnableV4Compat);
if (dwErr isnot NO_ERROR) {
dwErr = ERROR_INVALID_PARAMETER;
break;
}
dwBitVector |= BM_ENABLE_V4COMPAT;
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
}
// Now do the sets
dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, KEY_GLOBAL, 0,
NULL, 0, KEY_ALL_ACCESS, NULL, &hGlobal, NULL);
if (dwErr != NO_ERROR) {
return dwErr;
}
if (dwBitVector & BM_ENABLE_6OVER4) {
dwErr = SetInteger(hGlobal, KEY_ENABLE_6OVER4, stEnable6over4);
if (dwErr != NO_ERROR)
return dwErr;
}
if (dwBitVector & BM_ENABLE_V4COMPAT) {
dwErr = SetInteger(hGlobal, KEY_ENABLE_V4COMPAT, stEnableV4Compat);
if (dwErr != NO_ERROR)
return dwErr;
}
RegCloseKey(hGlobal);
Ip6to4PokeService();
return ERROR_OKAY;
}
DWORD
ShowIpv6StateConfig(
IN BOOL Dumping
)
{
DWORD dwErr = NO_ERROR;
HKEY hGlobal;
STATE stEnable6over4;
STATE stEnableV4Compat;
dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KEY_GLOBAL, 0, KEY_QUERY_VALUE,
&hGlobal);
if (dwErr != NO_ERROR) {
hGlobal = INVALID_HANDLE_VALUE;
dwErr = NO_ERROR;
}
stEnable6over4 = GetInteger(hGlobal, KEY_ENABLE_6OVER4, VAL_DEFAULT);
stEnableV4Compat = GetInteger(hGlobal, KEY_ENABLE_V4COMPAT, VAL_DEFAULT);
RegCloseKey(hGlobal);
if (Dumping) {
if ((stEnable6over4 != VAL_DEFAULT) ||
(stEnableV4Compat != VAL_DEFAULT)) {
DisplayMessageT(DMP_IP6TO4_SET_STATE);
if (stEnable6over4 != VAL_DEFAULT) {
DisplayMessageT(DMP_STRING_ARG, TOKEN_6OVER4,
pwszStateString[stEnable6over4]);
}
if (stEnableV4Compat != VAL_DEFAULT) {
DisplayMessageT(DMP_STRING_ARG, TOKEN_V4COMPAT,
pwszStateString[stEnableV4Compat]);
}
DisplayMessage(g_hModule, MSG_NEWLINE);
}
} else {
DisplayMessage(g_hModule, MSG_6OVER4_STATE,
pwszStateString[stEnable6over4]);
// DisplayMessage(g_hModule, MSG_V4COMPAT_STATE,
// pwszStateString[stEnableV4Compat]);
}
return dwErr;
}
DWORD
HandleShowState(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
return ShowIpv6StateConfig(FALSE);
}
#define KEY_DNS_SERVER_LIST L"NameServer"
DWORD
GetDnsServerList(
IN PWCHAR pwszIfFriendlyName,
IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
OUT IN6_ADDR **ppipDnsList,
OUT DWORD *pdwNumEntries
)
/*++
Routine Description:
Reads the list of DNS servers from the registry and returns them in
an array which includes space for at least one more server. The
caller is responsible for freeing this space with FREE().
--*/
{
HKEY hInterfaces = INVALID_HANDLE_VALUE, hIf = INVALID_HANDLE_VALUE;
DWORD dwErr = NO_ERROR, Count = 0;
WCHAR Servers[800], *p, *pend;
DWORD i;
IN6_ADDR *pipDnsList = NULL;
SOCKADDR_IN6 saddr;
DWORD Length;
PCHAR pszAdapterName;
dwErr = MapFriendlyNameToAdapterName(NULL, pwszIfFriendlyName,
pAdapterInfo, &pszAdapterName);
if (dwErr != NO_ERROR) {
goto Cleanup;
}
Servers[0] = L'\0';
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, KEY_IPV6_INTERFACES, 0, GENERIC_READ,
&hInterfaces) != NO_ERROR) {
goto HaveString;
}
if (RegOpenKeyExA(hInterfaces, pszAdapterName, 0, GENERIC_READ, &hIf)
== NO_ERROR) {
GetString(hIf, KEY_DNS_SERVER_LIST, Servers, 800);
}
HaveString:
// Count one server for each delimiter, plus one at the end, plus
// one more which the caller might want to add to the array which
// we allocate.
for (p = Servers; *p; p++) {
if (*p == ' ' || *p == ',' || *p == ';') {
Count++;
}
}
Count += 2;
//
// Now allocate an array of IN6_ADDR structures, and copy all the
// addresses into it.
//
pipDnsList = MALLOC(sizeof(IN6_ADDR) * Count);
if (pipDnsList == NULL) {
dwErr = GetLastError();
goto Cleanup;
}
Count = 0;
for (p = wcstok(Servers, L" ,;"); p; p = wcstok(NULL, L" ,;")) {
Length = sizeof(saddr);
if (WSAStringToAddressW(p, AF_INET6, NULL, (LPSOCKADDR)&saddr,
&Length) == NO_ERROR) {
pipDnsList[Count++] = saddr.sin6_addr;
}
}
Cleanup:
if (hIf != INVALID_HANDLE_VALUE) {
RegCloseKey(hIf);
}
if (hInterfaces != INVALID_HANDLE_VALUE) {
RegCloseKey(hInterfaces);
}
*pdwNumEntries = Count;
*ppipDnsList = pipDnsList;
return dwErr;
}
DWORD
SetDnsServerList(
IN PWCHAR pwszIfFriendlyName,
IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
IN IN6_ADDR *pipDnsList,
IN DWORD dwNumEntries
)
/*++
Routine Description:
Writes the list of DNS servers to the registry, overwriting any
previously list.
--*/
{
DWORD dwErr;
WCHAR Servers[800], *p = Servers;
ULONG LengthLeft = 800, Length;
DWORD i;
SOCKADDR_IN6 saddr;
HKEY hInterfaces, hIf;
PCHAR pszAdapterName;
dwErr = MapFriendlyNameToAdapterName(NULL, pwszIfFriendlyName,
pAdapterInfo, &pszAdapterName);
if (dwErr != NO_ERROR) {
return dwErr;
}
dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE, KEY_IPV6_INTERFACES, 0,
NULL, 0, KEY_ALL_ACCESS, NULL, &hInterfaces, NULL);
if (dwErr != NO_ERROR) {
return dwErr;
}
dwErr = RegCreateKeyExA(hInterfaces, pszAdapterName, 0,
NULL, 0, KEY_ALL_ACCESS, NULL, &hIf, NULL);
if (dwErr != NO_ERROR) {
RegCloseKey(hInterfaces);
return dwErr;
}
// Compose the string value, making sure to prevent a buffer overrun.
Servers[0] = L'\0';
ZeroMemory(&saddr, sizeof(saddr));
saddr.sin6_family = AF_INET6;
for (i = 0; i < dwNumEntries; i++) {
saddr.sin6_addr = pipDnsList[i];
Length = LengthLeft;
if (WSAAddressToStringW((LPSOCKADDR)&saddr, sizeof(saddr), NULL,
p, &Length) != NO_ERROR) {
continue;
}
// Update string taking into account that Length includes the NULL
// byte.
LengthLeft -= Length;
p += (Length-1);
*p++ = L' ';
}
if (p > Servers) {
// Null out final delimiter.
p--;
*p = '\0';
}
dwErr = SetString(hIf, KEY_DNS_SERVER_LIST, Servers);
RegCloseKey(hIf);
RegCloseKey(hInterfaces);
return dwErr;
}
DWORD
HandleAddDns(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr = NO_ERROR;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, NS_REQ_PRESENT, FALSE},
{TOKEN_ADDRESS, NS_REQ_PRESENT, FALSE},
{TOKEN_INDEX, NS_REQ_ZERO, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i;
PWCHAR pwszIfFriendlyName = NULL;
IN6_ADDR ipAddress;
DWORD dwIndex = -1;
HKEY hInterfaces, hIf;
IN6_ADDR *ipDnsList;
DWORD dwNumEntries;
PIP_ADAPTER_ADDRESSES pAdapterInfo = NULL;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
if (dwErr isnot NO_ERROR) {
return dwErr;
}
for (i=0; i<dwArgCount-dwCurrentIndex; i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // ADDRESS
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipAddress);
break;
case 2: // INDEX
dwIndex = wcstoul(ppwcArguments[dwCurrentIndex + i], NULL, 10);
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
}
dwErr = MyGetAdaptersInfo(&pAdapterInfo);
if (dwErr != NO_ERROR) {
goto Cleanup;
}
dwErr = GetDnsServerList(pwszIfFriendlyName, pAdapterInfo, &ipDnsList,
&dwNumEntries);
if (dwErr != NO_ERROR) {
goto Cleanup;
}
if ((dwIndex == -1) || (dwIndex-1 == dwNumEntries)) {
// Append server.
ipDnsList[dwNumEntries++] = ipAddress;
} else if ((dwIndex == 0) || (dwIndex > dwNumEntries)) {
dwErr = ERROR_INVALID_PARAMETER;
goto Cleanup;
} else {
dwIndex--;
// Insert server at location 'dwIndex'.
for (i = dwNumEntries; i > dwIndex; i--) {
ipDnsList[i] = ipDnsList[i-1];
}
ipDnsList[dwIndex] = ipAddress;
dwNumEntries++;
}
dwErr = SetDnsServerList(pwszIfFriendlyName, pAdapterInfo, ipDnsList,
dwNumEntries);
Cleanup:
if (ipDnsList != NULL) {
FREE(ipDnsList);
}
if (pAdapterInfo != NULL) {
FREE(pAdapterInfo);
}
if (dwErr == NO_ERROR) {
dwErr = ERROR_OKAY;
}
return dwErr;
}
DWORD
HandleDelDns(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr = NO_ERROR;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, NS_REQ_PRESENT, FALSE},
{TOKEN_ADDRESS, NS_REQ_PRESENT, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i;
PWCHAR pwszIfFriendlyName = NULL;
IN6_ADDR ipAddress;
IN6_ADDR *ipDnsList;
BOOL bAll = FALSE;
DWORD dwNumEntries;
PIP_ADAPTER_ADDRESSES pAdapterInfo = NULL;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
if (dwErr isnot NO_ERROR) {
return dwErr;
}
for (i=0; i<dwArgCount-dwCurrentIndex; i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
case 1: // ADDRESS
{
DWORD dwRes;
TOKEN_VALUE rgEnums[] = {{TOKEN_VALUE_ALL, 1}};
dwErr = MatchEnumTag(g_hModule,
ppwcArguments[i + dwCurrentIndex],
NUM_TOKENS_IN_TABLE(rgEnums),
rgEnums,
&dwRes);
if (NO_ERROR == dwErr) {
bAll = TRUE;
} else {
dwErr = GetIpv6Address(ppwcArguments[i + dwCurrentIndex],
&ipAddress);
}
break;
}
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
}
dwErr = MyGetAdaptersInfo(&pAdapterInfo);
if (dwErr != NO_ERROR) {
goto Cleanup;
}
dwErr = GetDnsServerList(pwszIfFriendlyName, pAdapterInfo, &ipDnsList,
&dwNumEntries);
if (dwErr != NO_ERROR) {
goto Cleanup;
}
if (bAll) {
// Delete all entries.
dwNumEntries = 0;
} else {
// Find and delete the specified entry.
for (i = 0; i < dwNumEntries; i++) {
if (!memcmp(&ipAddress, &ipDnsList[i], sizeof(ipAddress))) {
break;
}
}
if (i == dwNumEntries) {
goto Cleanup;
}
for (; i + 1 < dwNumEntries; i++) {
ipDnsList[i] = ipDnsList[i+1];
}
dwNumEntries--;
}
dwErr = SetDnsServerList(pwszIfFriendlyName, pAdapterInfo, ipDnsList,
dwNumEntries);
Cleanup:
if (ipDnsList != NULL) {
FREE(ipDnsList);
}
if (pAdapterInfo != NULL) {
FREE(pAdapterInfo);
}
if (dwErr == NO_ERROR) {
dwErr = ERROR_OKAY;
}
return dwErr;
}
DWORD
ShowIfDnsServers(
IN BOOL bDump,
IN PIP_ADAPTER_ADDRESSES pAdapterInfo,
IN PWCHAR pwszIfFriendlyName,
IN OUT BOOL *pbHeaderDone
)
{
DWORD i, dwErr;
WCHAR buff[NI_MAXHOST];
SOCKADDR_IN6 saddr;
DWORD Length, dwNumEntries;
IN6_ADDR *ipDnsList;
dwErr = GetDnsServerList(pwszIfFriendlyName, pAdapterInfo, &ipDnsList,
&dwNumEntries);
if (dwErr != NO_ERROR) {
goto Error;
}
if (!bDump && (dwNumEntries > 0)) {
// DisplayMessage(g_hModule, MSG_DNS_SERVER_HEADER, pwszIfFriendlyName);
*pbHeaderDone = TRUE;
}
ZeroMemory(&saddr, sizeof(saddr));
saddr.sin6_family = AF_INET6;
for (i = 0; i < dwNumEntries; i++) {
saddr.sin6_addr = ipDnsList[i];
Length = sizeof(saddr);
if (WSAAddressToStringW((LPSOCKADDR)&saddr, sizeof(saddr), NULL,
buff, &Length) != NO_ERROR) {
continue;
}
if (bDump) {
DisplayMessageT(DMP_IPV6_ADD_DNS);
DisplayMessageT(DMP_QUOTED_STRING_ARG, TOKEN_INTERFACE,
pwszIfFriendlyName);
DisplayMessageT(DMP_STRING_ARG, TOKEN_ADDRESS, buff);
DisplayMessage(g_hModule, MSG_NEWLINE);
} else {
// DisplayMessage(g_hModule, MSG_DNS_SERVER, i+1, buff);
}
}
Error:
if (ipDnsList != NULL) {
FREE(ipDnsList);
}
return dwErr;
}
DWORD
ShowDnsServers(
IN BOOL bDump,
IN PWCHAR pwszIfFriendlyName
)
{
PIP_ADAPTER_ADDRESSES pIf, pAdapterInfo = NULL;
DWORD dwErr;
BOOL bHeaderDone = FALSE;
dwErr = MyGetAdaptersInfo(&pAdapterInfo);
if (dwErr != NO_ERROR) {
return dwErr;
}
if (pwszIfFriendlyName == NULL) {
for (pIf = pAdapterInfo; (dwErr == NO_ERROR) && pIf; pIf = pIf->Next) {
if (pIf->Ipv6IfIndex == 0) {
continue;
}
dwErr = ShowIfDnsServers(bDump, pAdapterInfo, pIf->FriendlyName,
&bHeaderDone);
}
} else {
dwErr = ShowIfDnsServers(bDump, pAdapterInfo, pwszIfFriendlyName,
&bHeaderDone);
}
if (!bDump) {
if (!bHeaderDone) {
DisplayMessage(g_hModule, MSG_IP_NO_ENTRIES);
}
if (dwErr == NO_ERROR) {
dwErr = ERROR_SUPPRESS_OUTPUT;
}
}
FREE(pAdapterInfo);
return dwErr;
}
DWORD
HandleShowDns(
IN LPCWSTR pwszMachine,
IN OUT LPWSTR *ppwcArguments,
IN DWORD dwCurrentIndex,
IN DWORD dwArgCount,
IN DWORD dwFlags,
IN LPCVOID pvData,
OUT BOOL *pbDone
)
{
DWORD dwErr = NO_ERROR;
TAG_TYPE pttTags[] = {{TOKEN_INTERFACE, NS_REQ_ZERO, FALSE}};
DWORD rgdwTagType[sizeof(pttTags)/sizeof(TAG_TYPE)];
DWORD i;
PWCHAR pwszIfFriendlyName = NULL;
// Parse arguments
dwErr = PreprocessCommand(g_hModule,
ppwcArguments,
dwCurrentIndex,
dwArgCount,
pttTags,
sizeof(pttTags)/sizeof(TAG_TYPE),
0,
sizeof(pttTags)/sizeof(TAG_TYPE),
rgdwTagType );
if (dwErr isnot NO_ERROR) {
return dwErr;
}
for (i=0; i<dwArgCount-dwCurrentIndex; i++) {
switch(rgdwTagType[i]) {
case 0: // INTERFACE
pwszIfFriendlyName = ppwcArguments[i + dwCurrentIndex];
break;
default:
dwErr = ERROR_INVALID_SYNTAX;
break;
}
if (dwErr isnot NO_ERROR) {
return dwErr;
}
}
dwErr = ShowDnsServers(FALSE, pwszIfFriendlyName);
if (dwErr == NO_ERROR) {
dwErr = ERROR_OKAY;
}
return dwErr;
}