windows-nt/Source/XPSP1/NT/net/ipsec/spd/server/address.c
2020-09-26 16:20:57 +08:00

453 lines
8.3 KiB
C

#include"precomp.h"
DWORD
VerifyAddresses(
ADDR Addr,
BOOL bAcceptMe,
BOOL bIsDesAddr
)
{
DWORD dwError = 0;
BOOL bIsValid = FALSE;
switch (Addr.AddrType) {
case IP_ADDR_UNIQUE:
bIsValid = bIsValidIPAddress(
ntohl(Addr.uIpAddr),
bAcceptMe,
bIsDesAddr
);
if (!bIsValid) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
break;
case IP_ADDR_SUBNET:
dwError = VerifySubNetAddress(
ntohl(Addr.uIpAddr),
ntohl(Addr.uSubNetMask),
bIsDesAddr
);
BAIL_ON_WIN32_ERROR(dwError);
break;
case IP_ADDR_INTERFACE:
if (Addr.uIpAddr) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
break;
default:
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
break;
}
error:
return (dwError);
}
BOOL
EqualAddresses(
IN ADDR OldAddr,
IN ADDR NewAddr
)
{
BOOL bMatches = FALSE;
if (OldAddr.AddrType == NewAddr.AddrType) {
switch(OldAddr.AddrType) {
case IP_ADDR_UNIQUE:
if (OldAddr.uIpAddr == NewAddr.uIpAddr) {
bMatches = TRUE;
}
break;
case IP_ADDR_SUBNET:
if ((OldAddr.uIpAddr == NewAddr.uIpAddr) &&
(OldAddr.uSubNetMask == NewAddr.uSubNetMask)) {
bMatches = TRUE;
}
break;
case IP_ADDR_INTERFACE:
if (!memcmp(
&OldAddr.gInterfaceID,
&NewAddr.gInterfaceID,
sizeof(GUID)) &&
(OldAddr.uIpAddr == NewAddr.uIpAddr)) {
bMatches = TRUE;
}
break;
}
}
return (bMatches);
}
VOID
CopyAddresses(
IN ADDR InAddr,
OUT PADDR pOutAddr
)
{
pOutAddr->AddrType = InAddr.AddrType;
switch (InAddr.AddrType) {
case IP_ADDR_UNIQUE:
pOutAddr->uIpAddr = InAddr.uIpAddr;
pOutAddr->uSubNetMask = IP_ADDRESS_MASK_NONE;
memset(&pOutAddr->gInterfaceID, 0, sizeof(GUID));
break;
case IP_ADDR_SUBNET:
pOutAddr->uIpAddr = InAddr.uIpAddr;
pOutAddr->uSubNetMask = InAddr.uSubNetMask;
memset(&pOutAddr->gInterfaceID, 0, sizeof(GUID));
break;
case IP_ADDR_INTERFACE:
pOutAddr->uIpAddr = InAddr.uIpAddr;
pOutAddr->uSubNetMask = IP_ADDRESS_MASK_NONE;
memcpy(
&pOutAddr->gInterfaceID,
&InAddr.gInterfaceID,
sizeof(GUID)
);
break;
}
}
BOOL
AddressesConflict(
ADDR SrcAddr,
ADDR DesAddr
)
{
if ((SrcAddr.AddrType == IP_ADDR_UNIQUE) &&
(DesAddr.AddrType == IP_ADDR_UNIQUE)) {
if (SrcAddr.uIpAddr == DesAddr.uIpAddr) {
return (TRUE);
}
}
if ((SrcAddr.AddrType == IP_ADDR_INTERFACE) &&
(DesAddr.AddrType == IP_ADDR_INTERFACE)) {
return (TRUE);
}
return (FALSE);
}
VOID
FreeAddresses(
ADDR Addr
)
{
switch (Addr.AddrType) {
case (IP_ADDR_UNIQUE):
case (IP_ADDR_SUBNET):
case (IP_ADDR_INTERFACE):
break;
}
}
DWORD
VerifySubNetAddress(
ULONG uSubNetAddr,
ULONG uSubNetMask,
BOOL bIsDesAddr
)
{
DWORD dwError = 0;
BOOL bIsValid = FALSE;
if (uSubNetAddr == SUBNET_ADDRESS_ANY) {
if (uSubNetMask != SUBNET_MASK_ANY) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
}
else {
bIsValid = bIsValidSubnet(
uSubNetAddr,
uSubNetMask,
bIsDesAddr
);
if (!bIsValid) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
}
error:
return (dwError);
}
BOOL
bIsValidIPMask(
ULONG uMask
)
{
BOOL bValidMask = FALSE;
ULONG uTestMask = 0;
//
// Mask must be contiguous bits.
//
for (uTestMask = 0xFFFFFFFF; uTestMask; uTestMask <<= 1) {
if (uTestMask == uMask) {
bValidMask = TRUE;
break;
}
}
return (bValidMask);
}
BOOL
bIsValidIPAddress(
ULONG uIpAddr,
BOOL bAcceptMe,
BOOL bIsDesAddr
)
{
ULONG uHostMask = IN_CLASSA_HOST; // Default host mask.
//
// Accept the address if its "me".
//
if (bAcceptMe) {
if (uIpAddr == IP_ADDRESS_ME) {
return TRUE;
}
}
//
// Reject if its a multicast address and is not the
// destination address.
//
if (IN_CLASSD(uIpAddr)) {
if (bIsDesAddr) {
return TRUE;
}
else {
return FALSE;
}
}
//
// Reject if its a Class E address.
//
if (IN_CLASSE(uIpAddr)) {
return FALSE;
}
//
// Reject if the first octet is zero.
//
if (!(IN_CLASSA_NET & uIpAddr)) {
return FALSE;
}
//
// Use default mask based on Class when none is provided.
//
if (IN_CLASSA(uIpAddr)) {
uHostMask = IN_CLASSA_HOST;
}
else if (IN_CLASSB(uIpAddr)) {
uHostMask = IN_CLASSB_HOST;
}
else if (IN_CLASSC(uIpAddr)) {
uHostMask = IN_CLASSC_HOST;
}
//
// Accept address when host portion is non-zero.
//
if (uHostMask & uIpAddr) {
return TRUE;
}
return FALSE;
}
BOOL
bIsValidSubnet(
ULONG uIpAddr,
ULONG uMask,
BOOL bIsDesAddr
)
{
ULONG uHostMask = 0;
//
// Reject if its a multicast address and is not the
// destination address.
//
if (IN_CLASSD(uIpAddr)) {
if (!bIsDesAddr) {
return FALSE;
}
}
//
// Reject if its a Class E address.
//
if (IN_CLASSE(uIpAddr)) {
return FALSE;
}
//
// Reject if the first octet is zero.
//
if (!(IN_CLASSA_NET & uIpAddr)) {
return FALSE;
}
//
// If the mask is invalid then return.
//
if (!bIsValidIPMask(uMask)) {
return FALSE;
}
//
// Use the provided subnet mask to generate the host mask.
//
uHostMask = 0xFFFFFFFF ^ uMask;
//
// Validate the address and the mask.
//
if (IN_CLASSA(uIpAddr)) {
if (IN_CLASSA_NET > uMask) {
return FALSE;
}
}
else if (IN_CLASSB(uIpAddr)) {
if (IN_CLASSB_NET > uMask) {
return FALSE;
}
}
else if (IN_CLASSC(uIpAddr)) {
if (IN_CLASSC_NET > uMask) {
//
// Superset of Class C Subnet Address.
//
return TRUE;
}
}
//
// Accept address only when the host portion is zero, network
// portion is non-zero and first octet is non-zero.
//
if (!(uHostMask & uIpAddr) &&
(uMask & uIpAddr) &&
(IN_CLASSA_NET & uIpAddr)) {
return TRUE;
}
return FALSE;
}
BOOL
MatchAddresses(
ADDR AddrToMatch,
ADDR AddrTemplate
)
{
switch (AddrTemplate.AddrType) {
case IP_ADDR_UNIQUE:
if ((AddrToMatch.uIpAddr & AddrToMatch.uSubNetMask) !=
(AddrTemplate.uIpAddr & AddrToMatch.uSubNetMask)) {
return (FALSE);
}
break;
case IP_ADDR_SUBNET:
if ((AddrToMatch.uIpAddr & AddrToMatch.uSubNetMask) !=
((AddrTemplate.uIpAddr & AddrTemplate.uSubNetMask)
& AddrToMatch.uSubNetMask)) {
return (FALSE);
}
break;
case IP_ADDR_INTERFACE:
if (memcmp(
&AddrToMatch.gInterfaceID,
&AddrTemplate.gInterfaceID,
sizeof(GUID))) {
return (FALSE);
}
break;
}
return (TRUE);
}
DWORD
ApplyMulticastFilterValidation(
ADDR Addr,
BOOL bCreateMirror
)
{
DWORD dwError = 0;
if (((Addr.AddrType == IP_ADDR_UNIQUE) ||
(Addr.AddrType == IP_ADDR_SUBNET)) &&
(IN_CLASSD(ntohl(Addr.uIpAddr))) &&
bCreateMirror) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
error:
return (dwError);
}