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.
1070 lines
35 KiB
1070 lines
35 KiB
/*++
|
|
|
|
Copyright (c) 1999, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
routing\netsh\ip\protocols\vrrphlpcfg.c
|
|
|
|
Abstract:
|
|
|
|
Virtual Router Redundancy Protocol configuration implementation.
|
|
This module contains configuration routines which are relied upon
|
|
by vrrphlpopt.c. The routines retrieve, update, and display
|
|
the configuration for the VRRP protocol.
|
|
|
|
This file also contains default configuration settings
|
|
for VRRP.
|
|
|
|
N.B. The display routines require special attention since display
|
|
may result in a list of commands sent to a 'dump' file, or in a
|
|
textual presentation of the configuration to a console window.
|
|
In the latter case, we use non-localizable output routines to generate
|
|
a script-like description of the configuration. In the former case,
|
|
we use localizable routines to generate a human-readable description.
|
|
|
|
Author:
|
|
|
|
Peeyush Ranjan (peeyushr) 3-Mar-1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#define Malloc(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
|
#define Free(x) HeapFree(GetProcessHeap(), 0, (x))
|
|
|
|
static VRRP_GLOBAL_CONFIG
|
|
g_VrrpGlobalDefault =
|
|
{
|
|
VRRP_LOGGING_ERROR
|
|
};
|
|
|
|
static PUCHAR g_pVrrpGlobalDefault = (PUCHAR)&g_VrrpGlobalDefault;
|
|
|
|
static VRRP_IF_CONFIG g_VrrpInterfaceDefault =
|
|
{
|
|
0
|
|
};
|
|
|
|
static VRRP_VROUTER_CONFIG g_VrrpVrouterDefault =
|
|
{
|
|
1,
|
|
100,
|
|
1,
|
|
1,
|
|
0,
|
|
0,
|
|
{0,0,0,0,0,0,0,0
|
|
},
|
|
0
|
|
};
|
|
|
|
|
|
//
|
|
// Forward declarations
|
|
//
|
|
ULONG
|
|
ValidateVrrpInterfaceInfo(
|
|
PVRRP_IF_CONFIG InterfaceInfo
|
|
);
|
|
|
|
BOOL
|
|
FoundIpAddress(
|
|
DWORD IPAddress
|
|
);
|
|
|
|
//
|
|
// What follows are the arrays used to map values to strings and
|
|
// to map values to tokens. These, respectively, are used in the case
|
|
// where we are displaying to a 'dump' file and to a console window.
|
|
//
|
|
VALUE_STRING VrrpGlobalLogginStringArray[] = {
|
|
VRRP_LOGGING_NONE, STRING_LOGGING_NONE,
|
|
VRRP_LOGGING_ERROR, STRING_LOGGING_ERROR,
|
|
VRRP_LOGGING_WARN, STRING_LOGGING_WARN,
|
|
VRRP_LOGGING_INFO, STRING_LOGGING_INFO
|
|
};
|
|
|
|
VALUE_TOKEN VrrpGlobalLogginTokenArray[] = {
|
|
VRRP_LOGGING_NONE, TOKEN_OPT_VALUE_NONE,
|
|
VRRP_LOGGING_ERROR, TOKEN_OPT_VALUE_ERROR,
|
|
VRRP_LOGGING_WARN, TOKEN_OPT_VALUE_WARN,
|
|
VRRP_LOGGING_INFO, TOKEN_OPT_VALUE_INFO
|
|
};
|
|
|
|
VALUE_STRING VrrpAuthModeStringArray[] = {
|
|
VRRP_AUTHTYPE_NONE, STRING_AUTH_NONE,
|
|
VRRP_AUTHTYPE_PLAIN, STRING_AUTH_SIMPLEPASSWD,
|
|
VRRP_AUTHTYPE_IPHEAD, STRING_AUTH_IPHEADER
|
|
};
|
|
|
|
VALUE_TOKEN VrrpAuthModeTokenArray[] = {
|
|
VRRP_AUTHTYPE_NONE, TOKEN_OPT_VALUE_AUTH_NONE,
|
|
VRRP_AUTHTYPE_PLAIN, TOKEN_OPT_VALUE_AUTH_SIMPLE_PASSWORD,
|
|
VRRP_AUTHTYPE_IPHEAD, TOKEN_OPT_VALUE_AUTH_MD5
|
|
};
|
|
|
|
VALUE_STRING VrrpPreemptModeStringArray[] = {
|
|
TRUE, STRING_ENABLED,
|
|
FALSE, STRING_DISABLED
|
|
};
|
|
|
|
VALUE_TOKEN VrrpPreemptModeTokenArray[] = {
|
|
TRUE, TOKEN_OPT_VALUE_ENABLE,
|
|
FALSE,TOKEN_OPT_VALUE_DISABLE
|
|
};
|
|
|
|
typedef enum {
|
|
VrrpGlobalLoggingModeIndex,
|
|
VrrpAuthModeIndex,
|
|
VrrpPreemptModeIndex
|
|
} DISPLAY_VALUE_INDEX;
|
|
|
|
|
|
|
|
|
|
PTCHAR
|
|
QueryValueString(
|
|
HANDLE FileHandle,
|
|
DISPLAY_VALUE_INDEX Index,
|
|
ULONG Value
|
|
)
|
|
{
|
|
ULONG Count;
|
|
ULONG Error;
|
|
PTCHAR String = NULL;
|
|
PVALUE_STRING StringArray;
|
|
PVALUE_TOKEN TokenArray;
|
|
switch (Index) {
|
|
case VrrpGlobalLoggingModeIndex:
|
|
Count = NUM_VALUES_IN_TABLE(VrrpGlobalLogginStringArray);
|
|
StringArray = VrrpGlobalLogginStringArray;
|
|
TokenArray = VrrpGlobalLogginTokenArray;
|
|
break;
|
|
case VrrpAuthModeIndex:
|
|
Count = NUM_VALUES_IN_TABLE(VrrpAuthModeStringArray);
|
|
StringArray = VrrpAuthModeStringArray;
|
|
TokenArray = VrrpAuthModeTokenArray;
|
|
break;
|
|
case VrrpPreemptModeIndex:
|
|
Count = NUM_VALUES_IN_TABLE(VrrpPreemptModeStringArray);
|
|
StringArray = VrrpPreemptModeStringArray;
|
|
TokenArray = VrrpPreemptModeTokenArray;
|
|
break;
|
|
default:
|
|
return NULL;
|
|
}
|
|
Error =
|
|
GetAltDisplayString(
|
|
g_hModule,
|
|
FileHandle,
|
|
Value,
|
|
TokenArray,
|
|
StringArray,
|
|
Count,
|
|
&String
|
|
);
|
|
return Error ? NULL : String;
|
|
}
|
|
|
|
|
|
|
|
ULONG
|
|
MakeVrrpGlobalInfo(
|
|
OUT PUCHAR* GlobalInfo,
|
|
OUT PULONG GlobalInfoSize
|
|
)
|
|
{
|
|
*GlobalInfoSize = sizeof(VRRP_GLOBAL_CONFIG);
|
|
*GlobalInfo = Malloc(*GlobalInfoSize);
|
|
if (!*GlobalInfo) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
CopyMemory(*GlobalInfo, g_pVrrpGlobalDefault, *GlobalInfoSize);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
ULONG
|
|
CreateVrrpGlobalInfo(
|
|
OUT PVRRP_GLOBAL_CONFIG* GlobalInfo,
|
|
IN DWORD LoggingLevel
|
|
)
|
|
{
|
|
DWORD GlobalInfoSize;
|
|
GlobalInfoSize = sizeof(PVRRP_GLOBAL_CONFIG);
|
|
*GlobalInfo = Malloc(GlobalInfoSize);
|
|
if (!*GlobalInfo) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
CopyMemory(*GlobalInfo, g_pVrrpGlobalDefault, GlobalInfoSize);
|
|
(*GlobalInfo)->LoggingLevel = LoggingLevel;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
ULONG
|
|
MakeVrrpInterfaceInfo(
|
|
ROUTER_INTERFACE_TYPE InterfaceType,
|
|
OUT PUCHAR* InterfaceInfo,
|
|
OUT PULONG InterfaceInfoSize
|
|
)
|
|
{
|
|
//
|
|
//Why is this check done?
|
|
//
|
|
if (InterfaceType != ROUTER_IF_TYPE_DEDICATED) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
*InterfaceInfoSize = sizeof(VRRP_IF_CONFIG);
|
|
*InterfaceInfo = Malloc(*InterfaceInfoSize);
|
|
if (!*InterfaceInfo) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
CopyMemory(*InterfaceInfo, &g_VrrpInterfaceDefault, *InterfaceInfoSize);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
ULONG
|
|
MakeVrrpVRouterInfo(
|
|
IN OUT PUCHAR VRouterInfo
|
|
)
|
|
{
|
|
//
|
|
// Always assumed that the space has been preassigned
|
|
//
|
|
if (!VRouterInfo) {
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
CopyMemory(VRouterInfo,&g_VrrpVrouterDefault,sizeof(g_VrrpVrouterDefault));
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
ULONG
|
|
ShowVrrpGlobalInfo(
|
|
HANDLE FileHandle
|
|
)
|
|
{
|
|
ULONG Count = 0;
|
|
ULONG Error;
|
|
PVRRP_GLOBAL_CONFIG GlobalInfo = NULL;
|
|
ULONG i;
|
|
PTCHAR LoggingLevel = NULL;
|
|
ULONG Size;
|
|
do {
|
|
//
|
|
// Retrieve the global configuration for the VRRP,
|
|
// and format its contents to the output file or console.
|
|
//
|
|
Error =
|
|
IpmontrGetInfoBlockFromGlobalInfo(
|
|
MS_IP_VRRP,
|
|
(PUCHAR*)&GlobalInfo,
|
|
&Size,
|
|
&Count
|
|
);
|
|
if (Error) {
|
|
break;
|
|
} else if (!(Count * Size)) {
|
|
Error = ERROR_NOT_FOUND; break;
|
|
}
|
|
LoggingLevel =
|
|
QueryValueString(
|
|
FileHandle, VrrpGlobalLoggingModeIndex, GlobalInfo->LoggingLevel
|
|
);
|
|
if (!LoggingLevel) { break; }
|
|
if (FileHandle) {
|
|
DisplayMessageT(DMP_VRRP_INSTALL);
|
|
DisplayMessageT(
|
|
DMP_VRRP_SET_GLOBAL,
|
|
TOKEN_OPT_LOGGINGLEVEL, LoggingLevel
|
|
);
|
|
} else {
|
|
DisplayMessage(
|
|
g_hModule,
|
|
MSG_VRRP_GLOBAL_INFO,
|
|
LoggingLevel
|
|
);
|
|
}
|
|
} while(FALSE);
|
|
|
|
if (LoggingLevel) { Free(LoggingLevel); }
|
|
if (GlobalInfo) { Free(GlobalInfo); }
|
|
if (!FileHandle && Error) {
|
|
if (Error == ERROR_NOT_FOUND) {
|
|
DisplayMessage(g_hModule, EMSG_PROTO_NO_GLOBAL_INFO);
|
|
} else {
|
|
DisplayError(g_hModule, Error);
|
|
}
|
|
}
|
|
return Error;
|
|
}
|
|
|
|
ULONG
|
|
ShowVrrpAllInterfaceInfo(
|
|
HANDLE FileHandle
|
|
)
|
|
{
|
|
DWORD dwErr, dwCount, dwTotal;
|
|
DWORD dwNumParsed, i, dwNumBlocks=1, dwSize, dwIfType;
|
|
PBYTE pBuffer;
|
|
PMPR_INTERFACE_0 pmi0;
|
|
WCHAR wszIfDesc[MAX_INTERFACE_NAME_LEN + 1];
|
|
|
|
//
|
|
// dump vrrp config for all interfaces
|
|
//
|
|
|
|
dwErr = IpmontrInterfaceEnum((PBYTE *) &pmi0,
|
|
&dwCount,
|
|
&dwTotal);
|
|
|
|
if(dwErr != NO_ERROR)
|
|
{
|
|
DisplayError(g_hModule,
|
|
dwErr);
|
|
return dwErr;
|
|
}
|
|
|
|
for(i = 0; i < dwCount; i++)
|
|
{
|
|
// make sure that vrrp is configured on that interface
|
|
|
|
dwErr = IpmontrGetInfoBlockFromInterfaceInfo(pmi0[i].wszInterfaceName,
|
|
MS_IP_VRRP,
|
|
&pBuffer,
|
|
&dwSize,
|
|
&dwNumBlocks,
|
|
&dwIfType);
|
|
if (dwErr != NO_ERROR) {
|
|
continue;
|
|
}
|
|
else {
|
|
HEAP_FREE(pBuffer) ;
|
|
}
|
|
|
|
|
|
ShowVrrpInterfaceInfo(FileHandle, pmi0[i].wszInterfaceName);
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
ULONG
|
|
ShowVrrpInterfaceInfo(
|
|
HANDLE FileHandle,
|
|
PWCHAR InterfaceName
|
|
)
|
|
{
|
|
ULONG Count = 0;
|
|
ULONG Error;
|
|
PVRRP_IF_CONFIG InterfaceInfo;
|
|
PTCHAR AuthType = NULL;
|
|
ULONG Size;
|
|
ULONG dwLength;
|
|
TCHAR Title[MAX_INTERFACE_NAME_LEN + 1];
|
|
ROUTER_INTERFACE_TYPE Type;
|
|
ULONG Index;
|
|
ULONG IPIndex;
|
|
BYTE Password[VRRP_MAX_AUTHKEY_SIZE];
|
|
PTCHAR IPAddresses = NULL;
|
|
TCHAR Address[VRRP_IPADDR_LENGTH+1];
|
|
PVRRP_VROUTER_CONFIG PVrouter;
|
|
PTCHAR PreemptMode = NULL;
|
|
|
|
do {
|
|
//
|
|
// Retrieve the interface's configuration
|
|
// and format it to the output file or console.
|
|
//
|
|
Error =
|
|
IpmontrGetInfoBlockFromInterfaceInfo(
|
|
InterfaceName,
|
|
MS_IP_VRRP,
|
|
(PUCHAR*)&InterfaceInfo,
|
|
&Size,
|
|
&Count,
|
|
&Type
|
|
);
|
|
if (Error) {
|
|
break;
|
|
} else if (!(Count * Size)) {
|
|
Error = ERROR_NOT_FOUND; break;
|
|
}
|
|
Size = sizeof(Title);
|
|
Error = IpmontrGetFriendlyNameFromIfName(InterfaceName, Title, &Size);
|
|
if (Error) {
|
|
Error = ERROR_NO_SUCH_INTERFACE;
|
|
break;
|
|
}
|
|
if (FileHandle) {
|
|
DisplayMessage(g_hModule, DMP_VRRP_INTERFACE_HEADER, Title);
|
|
DisplayMessageT(DMP_VRRP_ADD_INTERFACE,
|
|
TOKEN_OPT_NAME, Title);
|
|
if (InterfaceInfo->VrouterCount) {
|
|
for (Index = 0 , PVrouter = VRRP_FIRST_VROUTER_CONFIG(InterfaceInfo);
|
|
Index < InterfaceInfo->VrouterCount;
|
|
Index++ , PVrouter = VRRP_NEXT_VROUTER_CONFIG(PVrouter)) {
|
|
for (IPIndex = 0; IPIndex < PVrouter->IPCount;
|
|
IPIndex++) {
|
|
IP_TO_TSTR(Address,
|
|
&PVrouter->IPAddress[IPIndex]
|
|
);
|
|
DisplayMessageT(
|
|
DMP_VRRP_ADD_VRID,
|
|
TOKEN_OPT_NAME, Title,
|
|
TOKEN_OPT_VRID, PVrouter->VRID,
|
|
TOKEN_OPT_IPADDRESS, Address
|
|
);
|
|
}
|
|
|
|
AuthType =
|
|
QueryValueString(
|
|
FileHandle, VrrpAuthModeIndex,
|
|
PVrouter->AuthenticationType
|
|
);
|
|
if (!AuthType) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
CopyMemory(Password,PVrouter->AuthenticationData,
|
|
VRRP_MAX_AUTHKEY_SIZE);
|
|
DisplayMessageT(
|
|
DMP_VRRP_SET_INTERFACE,
|
|
TOKEN_OPT_NAME, Title,
|
|
TOKEN_OPT_VRID, PVrouter->VRID,
|
|
TOKEN_OPT_AUTH,
|
|
(PVrouter->AuthenticationType == VRRP_AUTHTYPE_NONE) ?
|
|
TOKEN_OPT_VALUE_AUTH_NONE : ((PVrouter->AuthenticationType
|
|
== VRRP_AUTHTYPE_PLAIN) ? TOKEN_OPT_VALUE_AUTH_SIMPLE_PASSWORD :
|
|
TOKEN_OPT_VALUE_AUTH_MD5 ) ,
|
|
TOKEN_OPT_PASSWD, Password[0], Password[1], Password[2],
|
|
Password[3], Password[4], Password[5],Password[6], Password[7],
|
|
TOKEN_OPT_ADVTINTERVAL, PVrouter->AdvertisementInterval,
|
|
TOKEN_OPT_PRIO,PVrouter->ConfigPriority,
|
|
TOKEN_OPT_PREEMPT, PVrouter->PreemptMode? TOKEN_OPT_VALUE_ENABLE :
|
|
TOKEN_OPT_VALUE_DISABLE
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
DisplayMessage(g_hModule, MSG_VRRP_INTERFACE_INFO,Title,
|
|
InterfaceInfo->VrouterCount);
|
|
for (Index = 0, PVrouter = VRRP_FIRST_VROUTER_CONFIG(InterfaceInfo);
|
|
Index < InterfaceInfo->VrouterCount;
|
|
Index++, PVrouter = VRRP_NEXT_VROUTER_CONFIG(PVrouter)) {
|
|
AuthType =
|
|
QueryValueString(
|
|
FileHandle, VrrpAuthModeIndex,
|
|
PVrouter->AuthenticationType
|
|
);
|
|
if (!AuthType) {
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
CopyMemory(Password,PVrouter->AuthenticationData,
|
|
VRRP_MAX_AUTHKEY_SIZE);
|
|
//
|
|
// Allocate space for each IP address, a space+comma each and also a
|
|
// null terminator
|
|
//
|
|
IPAddresses = Malloc(dwLength = (((VRRP_IPADDR_LENGTH+2)*sizeof(TCHAR)*
|
|
PVrouter->IPCount)+1));
|
|
if (!IPAddresses) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
|
|
//
|
|
// Set AuthType to 0 which will cause a break from the outer loop
|
|
//
|
|
|
|
AuthType = 0;
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
ZeroMemory(IPAddresses,dwLength);
|
|
//
|
|
// Now build the IP address list from the addresses given
|
|
//
|
|
for (IPIndex = 0; IPIndex < PVrouter->IPCount; IPIndex++ ) {
|
|
IP_TO_TSTR(Address,&PVrouter->IPAddress[IPIndex]);
|
|
wcscat(IPAddresses,Address);
|
|
if (IPIndex != (ULONG)(PVrouter->IPCount-1)) {
|
|
wcscat(IPAddresses,L", ");
|
|
}
|
|
}
|
|
PreemptMode =
|
|
QueryValueString(
|
|
FileHandle,
|
|
VrrpPreemptModeIndex,
|
|
PVrouter->PreemptMode
|
|
);
|
|
if (!PreemptMode) { break; }
|
|
|
|
DisplayMessage(
|
|
g_hModule,
|
|
MSG_VRRP_VRID_INFO,
|
|
PVrouter->VRID,
|
|
IPAddresses,
|
|
AuthType,
|
|
Password[0], Password[1], Password[2], Password[3],
|
|
Password[4], Password[5], Password[6], Password[7],
|
|
PVrouter->AdvertisementInterval,
|
|
PVrouter->ConfigPriority,
|
|
PreemptMode
|
|
);
|
|
}
|
|
}
|
|
if (!AuthType) {
|
|
break;
|
|
}
|
|
Error = NO_ERROR;
|
|
} while(FALSE);
|
|
if (AuthType) { Free(AuthType); }
|
|
Free(InterfaceInfo);
|
|
if (IPAddresses) Free(IPAddresses);
|
|
if (!FileHandle && Error) {
|
|
if (Error == ERROR_NOT_FOUND) {
|
|
DisplayMessage(g_hModule, EMSG_PROTO_NO_IF_INFO);
|
|
} else {
|
|
DisplayError(g_hModule, Error);
|
|
}
|
|
}
|
|
return Error;
|
|
}
|
|
|
|
ULONG
|
|
UpdateVrrpGlobalInfo(
|
|
PVRRP_GLOBAL_CONFIG GlobalInfo
|
|
)
|
|
{
|
|
ULONG Count;
|
|
ULONG Error;
|
|
PVRRP_GLOBAL_CONFIG NewGlobalInfo = NULL;
|
|
PVRRP_GLOBAL_CONFIG OldGlobalInfo = NULL;
|
|
ULONG Size;
|
|
|
|
do {
|
|
//
|
|
// Retrieve the existing global configuration.
|
|
//
|
|
Error =
|
|
IpmontrGetInfoBlockFromGlobalInfo(
|
|
MS_IP_VRRP,
|
|
(PUCHAR*)&OldGlobalInfo,
|
|
&Size,
|
|
&Count
|
|
);
|
|
if (Error) {
|
|
break;
|
|
} else if (!(Count * Size)) {
|
|
Error = ERROR_NOT_FOUND; break;
|
|
}
|
|
|
|
//
|
|
// Allocate a new structure, copy to it the original configuration,
|
|
//
|
|
|
|
NewGlobalInfo = Malloc(Count * Size);
|
|
if (!NewGlobalInfo) { Error = ERROR_NOT_ENOUGH_MEMORY; break; }
|
|
CopyMemory(NewGlobalInfo, OldGlobalInfo, Count * Size);
|
|
|
|
//
|
|
// Based on the changes requested, change the NewGlobalInfo.
|
|
// Since for VRRP there is only the logging level to change, we just set that.
|
|
//
|
|
|
|
NewGlobalInfo->LoggingLevel = GlobalInfo->LoggingLevel;
|
|
|
|
Error =
|
|
IpmontrSetInfoBlockInGlobalInfo(
|
|
MS_IP_VRRP,
|
|
(PUCHAR)NewGlobalInfo,
|
|
FIELD_OFFSET(IP_NAT_GLOBAL_INFO, Header) +
|
|
Count * Size,
|
|
1
|
|
);
|
|
} while(FALSE);
|
|
if (NewGlobalInfo) { Free(NewGlobalInfo); }
|
|
if (OldGlobalInfo) { Free(OldGlobalInfo); }
|
|
if (Error == ERROR_NOT_FOUND) {
|
|
DisplayMessage(g_hModule, EMSG_PROTO_NO_GLOBAL_INFO);
|
|
} else if (Error) {
|
|
DisplayError(g_hModule, Error);
|
|
}
|
|
return Error;
|
|
}
|
|
|
|
|
|
ULONG
|
|
UpdateVrrpInterfaceInfo(
|
|
PWCHAR InterfaceName,
|
|
PVRRP_VROUTER_CONFIG VRouterInfo,
|
|
ULONG BitVector,
|
|
BOOL AddInterface
|
|
)
|
|
{
|
|
ULONG Count;
|
|
ULONG Error;
|
|
PVRRP_IF_CONFIG NewInterfaceInfo = NULL;
|
|
PVRRP_IF_CONFIG OldInterfaceInfo = NULL;
|
|
PVRRP_VROUTER_CONFIG PVrouter = NULL;
|
|
ULONG Size;
|
|
ROUTER_INTERFACE_TYPE Type;
|
|
ULONG i;
|
|
|
|
if (!AddInterface && !BitVector) { return NO_ERROR; }
|
|
do {
|
|
//
|
|
// Retrieve the existing interface configuration.
|
|
// We will update this block below, as well as adding to or removing
|
|
// from it depending on the flags specified in 'BitVector'.
|
|
//
|
|
Error =
|
|
IpmontrGetInfoBlockFromInterfaceInfo(
|
|
InterfaceName,
|
|
MS_IP_VRRP,
|
|
(PUCHAR*)&OldInterfaceInfo,
|
|
&Size,
|
|
&Count,
|
|
&Type
|
|
);
|
|
if (Error) {
|
|
//
|
|
// No existing configuration is found. This is an error unless
|
|
// we are adding the interface anew, in which case we just
|
|
// create for ourselves a block containing the default settings.
|
|
//
|
|
if (!AddInterface) {
|
|
break;
|
|
} else {
|
|
Error = IpmontrGetInterfaceType(InterfaceName, &Type);
|
|
if (Error) {
|
|
break;
|
|
} else {
|
|
Count = 1;
|
|
Error =
|
|
MakeVrrpInterfaceInfo(
|
|
Type, (PUCHAR*)&OldInterfaceInfo, &Size
|
|
);
|
|
if (Error) { break; }
|
|
}
|
|
}
|
|
} else {
|
|
//
|
|
// There is configuration on the interface. If it is empty this is
|
|
// an error. If this is an add interface, and the info exists, it is
|
|
// an error.
|
|
//
|
|
if (!(Count * Size) && !AddInterface) {
|
|
Error = ERROR_NOT_FOUND; break;
|
|
}
|
|
else if (AddInterface) {
|
|
//
|
|
// We were asked to add an interface which already exists
|
|
//
|
|
DisplayMessage(g_hModule, EMSG_INTERFACE_EXISTS, InterfaceName);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
if (!BitVector) {
|
|
//
|
|
// Just add this interface without any additional info.
|
|
//
|
|
DWORD OldSize;
|
|
if (NewInterfaceInfo == NULL){
|
|
NewInterfaceInfo = Malloc((OldSize=GetVrrpIfInfoSize(OldInterfaceInfo))+
|
|
sizeof(VRRP_VROUTER_CONFIG));
|
|
if (!NewInterfaceInfo) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
CopyMemory(NewInterfaceInfo,OldInterfaceInfo,OldSize);
|
|
}
|
|
else{
|
|
if (!AddInterface || (OldInterfaceInfo->VrouterCount != 0)) {
|
|
//
|
|
// There is a prexisting VRID set. Check for this VRID in the list and then
|
|
// update it if required.
|
|
//
|
|
ASSERT(BitVector & VRRP_INTF_VRID_MASK);
|
|
for (i = 0, PVrouter = VRRP_FIRST_VROUTER_CONFIG(OldInterfaceInfo);
|
|
i < OldInterfaceInfo->VrouterCount;
|
|
i++, PVrouter = VRRP_NEXT_VROUTER_CONFIG(PVrouter)) {
|
|
if (PVrouter->VRID == VRouterInfo->VRID) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == OldInterfaceInfo->VrouterCount) {
|
|
//
|
|
// This is a new VRID, Add it.
|
|
//
|
|
DWORD OldSize;
|
|
|
|
//
|
|
// The IP address should be valid or else this is a set op.
|
|
//
|
|
if (!(BitVector & VRRP_INTF_IPADDR_MASK)){
|
|
DisplayMessage(
|
|
g_hModule, EMSG_INVALID_VRID,
|
|
VRouterInfo->VRID
|
|
);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
if (NewInterfaceInfo == NULL){
|
|
NewInterfaceInfo = Malloc((OldSize=GetVrrpIfInfoSize(
|
|
OldInterfaceInfo))+
|
|
sizeof(VRRP_VROUTER_CONFIG));
|
|
if (!NewInterfaceInfo) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
CopyMemory(NewInterfaceInfo, OldInterfaceInfo, OldSize);
|
|
PVrouter = (PVRRP_VROUTER_CONFIG)((PBYTE)NewInterfaceInfo+OldSize);
|
|
CopyMemory(PVrouter,VRouterInfo,sizeof(VRRP_VROUTER_CONFIG));
|
|
NewInterfaceInfo->VrouterCount++;
|
|
|
|
//
|
|
// Check if we own the IP address given. If yes, set the priority.
|
|
//
|
|
PVrouter->ConfigPriority =
|
|
FoundIpAddress(PVrouter->IPAddress[0]) ? 255 : 100;
|
|
}
|
|
else{
|
|
//
|
|
// This is an old VRID. Its priority should not need to be changed.
|
|
//
|
|
DWORD Offset, OldSize;
|
|
|
|
if(BitVector & VRRP_INTF_IPADDR_MASK) {
|
|
if ( ((PVrouter->ConfigPriority != 255) &&
|
|
(FoundIpAddress(VRouterInfo->IPAddress[0]))
|
|
)
|
|
||
|
|
((PVrouter->ConfigPriority == 255) &&
|
|
(!FoundIpAddress(VRouterInfo->IPAddress[0])))
|
|
) {
|
|
DisplayMessage(g_hModule, EMSG_BAD_OPTION_VALUE);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
//
|
|
// Add this IP address to the VRID specified.
|
|
//
|
|
if (NewInterfaceInfo == NULL){
|
|
NewInterfaceInfo = Malloc((OldSize = GetVrrpIfInfoSize(
|
|
OldInterfaceInfo))+
|
|
sizeof(DWORD));
|
|
if (!NewInterfaceInfo) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Shift all the VROUTER configs after the PVrouter by 1 DWORD.
|
|
//
|
|
Offset = (PUCHAR) VRRP_NEXT_VROUTER_CONFIG(PVrouter) -
|
|
(PUCHAR) OldInterfaceInfo;
|
|
CopyMemory(NewInterfaceInfo, OldInterfaceInfo, OldSize);
|
|
for (i = 0, PVrouter = VRRP_FIRST_VROUTER_CONFIG(NewInterfaceInfo);
|
|
i < NewInterfaceInfo->VrouterCount;
|
|
i++, PVrouter = VRRP_NEXT_VROUTER_CONFIG(PVrouter)) {
|
|
if (PVrouter->VRID == VRouterInfo->VRID) {
|
|
break;
|
|
}
|
|
}
|
|
ASSERT(i < NewInterfaceInfo->VrouterCount);
|
|
PVrouter->IPAddress[PVrouter->IPCount++] = VRouterInfo->IPAddress[0];
|
|
|
|
ASSERT(((PUCHAR)NewInterfaceInfo+Offset+sizeof(DWORD)) ==
|
|
(PUCHAR) VRRP_NEXT_VROUTER_CONFIG(PVrouter));
|
|
|
|
CopyMemory(VRRP_NEXT_VROUTER_CONFIG(PVrouter),
|
|
OldInterfaceInfo+Offset, OldSize-Offset);
|
|
} else {
|
|
//
|
|
// Set the new info block as the old info block and point to the
|
|
// vrouter block
|
|
//
|
|
if (NewInterfaceInfo == NULL){
|
|
NewInterfaceInfo = Malloc((OldSize = GetVrrpIfInfoSize(
|
|
OldInterfaceInfo)));
|
|
if (!NewInterfaceInfo) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
CopyMemory(NewInterfaceInfo, OldInterfaceInfo, OldSize);
|
|
for (i = 0, PVrouter = VRRP_FIRST_VROUTER_CONFIG(NewInterfaceInfo);
|
|
i < NewInterfaceInfo->VrouterCount;
|
|
i++, PVrouter = VRRP_NEXT_VROUTER_CONFIG(PVrouter)) {
|
|
if (PVrouter->VRID == VRouterInfo->VRID) {
|
|
break;
|
|
}
|
|
}
|
|
ASSERT(i < NewInterfaceInfo->VrouterCount);
|
|
}
|
|
|
|
if (BitVector & VRRP_INTF_AUTH_MASK) {
|
|
PVrouter->AuthenticationType = VRouterInfo->AuthenticationType;
|
|
}
|
|
if (BitVector & VRRP_INTF_PASSWD_MASK) {
|
|
CopyMemory(PVrouter->AuthenticationData,
|
|
VRouterInfo->AuthenticationData,
|
|
VRRP_MAX_AUTHKEY_SIZE);
|
|
}
|
|
if (BitVector & VRRP_INTF_ADVT_MASK) {
|
|
PVrouter->AdvertisementInterval = VRouterInfo->AdvertisementInterval;
|
|
}
|
|
if (BitVector & VRRP_INTF_PRIO_MASK) {
|
|
PVrouter->ConfigPriority = VRouterInfo->ConfigPriority;
|
|
}
|
|
if (BitVector & VRRP_INTF_PREEMPT_MASK) {
|
|
PVrouter->PreemptMode = VRouterInfo->PreemptMode;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ValidateVrrpInterfaceInfo(NewInterfaceInfo);
|
|
|
|
Error =
|
|
IpmontrSetInfoBlockInInterfaceInfo(
|
|
InterfaceName,
|
|
MS_IP_VRRP,
|
|
(PUCHAR)NewInterfaceInfo,
|
|
GetVrrpIfInfoSize(NewInterfaceInfo),
|
|
1
|
|
);
|
|
} while(FALSE);
|
|
if (NewInterfaceInfo) { Free(NewInterfaceInfo); }
|
|
if (OldInterfaceInfo) { Free(OldInterfaceInfo); }
|
|
if (Error == ERROR_NOT_FOUND) {
|
|
DisplayMessage(g_hModule, EMSG_PROTO_NO_IF_INFO);
|
|
} else if (Error) {
|
|
DisplayError(g_hModule, Error);
|
|
}
|
|
return Error;
|
|
}
|
|
|
|
ULONG
|
|
DeleteVrrpInterfaceInfo(
|
|
PWCHAR InterfaceName,
|
|
PVRRP_VROUTER_CONFIG VRouterInfo,
|
|
ULONG BitVector,
|
|
BOOL DeleteInterface
|
|
)
|
|
{
|
|
ULONG Count;
|
|
ULONG Error;
|
|
PVRRP_IF_CONFIG NewInterfaceInfo = NULL;
|
|
PVRRP_IF_CONFIG OldInterfaceInfo = NULL;
|
|
PVRRP_VROUTER_CONFIG PVrouter = NULL;
|
|
ULONG Size;
|
|
ROUTER_INTERFACE_TYPE Type;
|
|
ULONG i;
|
|
|
|
if (!DeleteInterface && !BitVector) { return NO_ERROR; }
|
|
do {
|
|
//
|
|
// Retrieve the existing interface configuration.
|
|
// We will update this block below, as well as adding to or removing
|
|
// from it depending on the flags specified in 'BitVector'.
|
|
//
|
|
Error =
|
|
IpmontrGetInfoBlockFromInterfaceInfo(
|
|
InterfaceName,
|
|
MS_IP_VRRP,
|
|
(PUCHAR*)&OldInterfaceInfo,
|
|
&Size,
|
|
&Count,
|
|
&Type
|
|
);
|
|
if (Error) {
|
|
//
|
|
// No existing configuration is found. This is an error.
|
|
//
|
|
break;
|
|
}
|
|
if (DeleteInterface) {
|
|
//
|
|
// Just delete this interface
|
|
//
|
|
Error = IpmontrDeleteInfoBlockFromInterfaceInfo(
|
|
InterfaceName,
|
|
MS_IP_VRRP
|
|
);
|
|
break;
|
|
} else {
|
|
DWORD OldSize;
|
|
PVRRP_VROUTER_CONFIG PVrouterNew;
|
|
//
|
|
// Look for the VRID and delete it.
|
|
//
|
|
for (i = 0, PVrouter = VRRP_FIRST_VROUTER_CONFIG(OldInterfaceInfo);
|
|
i < OldInterfaceInfo->VrouterCount;
|
|
i++, PVrouter = VRRP_NEXT_VROUTER_CONFIG(PVrouter)) {
|
|
if (PVrouter->VRID == VRouterInfo->VRID) {
|
|
break;
|
|
}
|
|
}
|
|
if (i >= OldInterfaceInfo->VrouterCount) {
|
|
DisplayMessage(g_hModule, EMSG_BAD_OPTION_VALUE);
|
|
Error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
NewInterfaceInfo = Malloc((OldSize=GetVrrpIfInfoSize(OldInterfaceInfo))-
|
|
VRRP_VROUTER_CONFIG_SIZE(PVrouter));
|
|
if (!NewInterfaceInfo) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
Error = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
NewInterfaceInfo->VrouterCount = OldInterfaceInfo->VrouterCount - 1;
|
|
PVrouterNew = VRRP_FIRST_VROUTER_CONFIG(NewInterfaceInfo);
|
|
for (i = 0, PVrouter = VRRP_FIRST_VROUTER_CONFIG(OldInterfaceInfo);
|
|
i < OldInterfaceInfo->VrouterCount;
|
|
i++, PVrouter = VRRP_NEXT_VROUTER_CONFIG(PVrouter)) {
|
|
if (PVrouter->VRID == VRouterInfo->VRID) {
|
|
continue;
|
|
}
|
|
CopyMemory(PVrouterNew,PVrouter,VRRP_VROUTER_CONFIG_SIZE(PVrouter));
|
|
PVrouterNew = VRRP_NEXT_VROUTER_CONFIG(PVrouterNew);
|
|
}
|
|
|
|
ValidateVrrpInterfaceInfo(NewInterfaceInfo);
|
|
|
|
Error =
|
|
IpmontrSetInfoBlockInInterfaceInfo(
|
|
InterfaceName,
|
|
MS_IP_VRRP,
|
|
(PUCHAR)NewInterfaceInfo,
|
|
GetVrrpIfInfoSize(NewInterfaceInfo),
|
|
1
|
|
);
|
|
}
|
|
|
|
} while(FALSE);
|
|
if (NewInterfaceInfo) { Free(NewInterfaceInfo); }
|
|
if (OldInterfaceInfo) { Free(OldInterfaceInfo); }
|
|
if (Error == ERROR_NOT_FOUND) {
|
|
DisplayMessage(g_hModule, EMSG_PROTO_NO_IF_INFO);
|
|
} else if (Error) {
|
|
DisplayError(g_hModule, Error);
|
|
}
|
|
return Error;
|
|
}
|
|
|
|
|
|
ULONG
|
|
ValidateVrrpInterfaceInfo(
|
|
PVRRP_IF_CONFIG InterfaceInfo
|
|
)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
GetVrrpIfInfoSize(
|
|
PVRRP_IF_CONFIG InterfaceInfo
|
|
)
|
|
{
|
|
DWORD Size = 0;
|
|
ULONG i;
|
|
PVRRP_VROUTER_CONFIG pvr;
|
|
|
|
Size += sizeof(InterfaceInfo->VrouterCount);
|
|
|
|
for (i = 0, pvr = VRRP_FIRST_VROUTER_CONFIG(InterfaceInfo);
|
|
i < InterfaceInfo->VrouterCount;
|
|
i++,pvr = VRRP_NEXT_VROUTER_CONFIG(pvr)) {
|
|
Size += VRRP_VROUTER_CONFIG_SIZE(pvr);
|
|
}
|
|
|
|
return Size;
|
|
}
|
|
|
|
BOOL
|
|
FoundIpAddress(
|
|
DWORD IPAddress
|
|
)
|
|
{
|
|
PMIB_IPADDRTABLE pTable = NULL;
|
|
DWORD Size = 0;
|
|
ULONG i;
|
|
BOOL Result;
|
|
|
|
GetIpAddrTable( pTable, &Size, TRUE);
|
|
pTable = Malloc(Size);
|
|
if (!pTable) {
|
|
DisplayMessage(g_hModule, EMSG_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
if (GetIpAddrTable(pTable,&Size,TRUE) != NO_ERROR){
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < pTable->dwNumEntries; i++) {
|
|
if (pTable->table[i].dwAddr == IPAddress)
|
|
break;
|
|
}
|
|
|
|
Result = (i < pTable->dwNumEntries);
|
|
|
|
Free(pTable);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
ULONG
|
|
SetArpRetryCount(
|
|
DWORD Value
|
|
)
|
|
{
|
|
HKEY hKey = NULL;
|
|
DWORD dwDisp;
|
|
ULONG dwErr = NO_ERROR;
|
|
|
|
do
|
|
{
|
|
dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
|
L"System\\CurrentControlSet\\Services\\Tcpip\\Parameters",
|
|
0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,
|
|
&hKey, &dwDisp);
|
|
if (dwErr != ERROR_SUCCESS) {
|
|
break;
|
|
}
|
|
dwErr = RegSetValueEx(hKey, L"ArpRetryCount", 0, REG_DWORD, (LPBYTE) &Value,
|
|
sizeof(DWORD));
|
|
} while (0);
|
|
|
|
if (hKey) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
if (dwErr == ERROR_SUCCESS) {
|
|
dwErr = NO_ERROR;
|
|
}
|
|
return dwErr;
|
|
}
|
|
|