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.
 
 
 
 
 
 

2366 lines
53 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
txspecific.c
Abstract:
This module contains all of the code to drive the
specific transport filter list management of IPSecSPD
Service.
Author:
abhisheV 29-October-1999
Environment
User Level: Win32
Revision History:
--*/
#include "precomp.h"
DWORD
ApplyTxTransform(
PINITXFILTER pFilter,
MATCHING_ADDR * pMatchingAddresses,
DWORD dwAddrCnt,
PINITXSFILTER * ppSpecificFilters
)
/*++
Routine Description:
This function expands a generic transport filter into its
corresponding specific filters.
Arguments:
pFilter - Generic filter to expand.
pMatchingAddresses - List of local ip addresses whose interface
type matches that of the filter.
dwAddrCnt - Number of local ip addresses in the list.
ppSpecificFilters - List of specific filters expanded for the
given generic filter.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PINITXSFILTER pSpecificFilters = NULL;
PINITXSFILTER pOutboundSpecificFilters = NULL;
PINITXSFILTER pInboundSpecificFilters = NULL;
PADDR pOutSrcAddrList = NULL;
DWORD dwOutSrcAddrCnt = 0;
PADDR pInSrcAddrList = NULL;
DWORD dwInSrcAddrCnt = 0;
PADDR pOutDesAddrList = NULL;
DWORD dwOutDesAddrCnt = 0;
PADDR pInDesAddrList = NULL;
DWORD dwInDesAddrCnt = 0;
//
// Form the outbound and inbound source and destination
// address lists.
//
dwError = FormTxOutboundInboundAddresses(
pFilter,
pMatchingAddresses,
dwAddrCnt,
&pOutSrcAddrList,
&dwOutSrcAddrCnt,
&pInSrcAddrList,
&dwInSrcAddrCnt,
&pOutDesAddrList,
&dwOutDesAddrCnt,
&pInDesAddrList,
&dwInDesAddrCnt
);
BAIL_ON_WIN32_ERROR(dwError);
//
// Form outbound specific filters.
//
dwError = FormSpecificTxFilters(
pFilter,
pOutSrcAddrList,
dwOutSrcAddrCnt,
pOutDesAddrList,
dwOutDesAddrCnt,
FILTER_DIRECTION_OUTBOUND,
&pOutboundSpecificFilters
);
BAIL_ON_WIN32_ERROR(dwError);
//
// Form inbound specific filters.
//
dwError = FormSpecificTxFilters(
pFilter,
pInSrcAddrList,
dwInSrcAddrCnt,
pInDesAddrList,
dwInDesAddrCnt,
FILTER_DIRECTION_INBOUND,
&pInboundSpecificFilters
);
BAIL_ON_WIN32_ERROR(dwError);
pSpecificFilters = pOutboundSpecificFilters;
AddToSpecificTxList(
&pSpecificFilters,
pInboundSpecificFilters
);
*ppSpecificFilters = pSpecificFilters;
cleanup:
if (pOutSrcAddrList) {
FreeSPDMemory(pOutSrcAddrList);
}
if (pInSrcAddrList) {
FreeSPDMemory(pInSrcAddrList);
}
if (pOutDesAddrList) {
FreeSPDMemory(pOutDesAddrList);
}
if (pInDesAddrList) {
FreeSPDMemory(pInDesAddrList);
}
return (dwError);
error:
if (pOutboundSpecificFilters) {
FreeIniTxSFilterList(pOutboundSpecificFilters);
}
if (pInboundSpecificFilters) {
FreeIniTxSFilterList(pInboundSpecificFilters);
}
*ppSpecificFilters = NULL;
goto cleanup;
}
DWORD
FormTxOutboundInboundAddresses(
PINITXFILTER pFilter,
MATCHING_ADDR * pMatchingAddresses,
DWORD dwAddrCnt,
PADDR * ppOutSrcAddrList,
PDWORD pdwOutSrcAddrCnt,
PADDR * ppInSrcAddrList,
PDWORD pdwInSrcAddrCnt,
PADDR * ppOutDesAddrList,
PDWORD pdwOutDesAddrCnt,
PADDR * ppInDesAddrList,
PDWORD pdwInDesAddrCnt
)
/*++
Routine Description:
This function forms the outbound and inbound source and
destination address sets for a generic filter.
Arguments:
pFilter - Generic filter under consideration.
pMatchingAddresses - List of local ip addresses whose interface
type matches that of the filter.
dwAddrCnt - Number of local ip addresses in the list.
ppOutSrcAddrList - List of outbound source addresses.
pdwOutSrcAddrCnt - Number of addresses in the outbound
source address list.
ppInSrcAddrList - List of inbound source addresses.
pdwInSrcAddrCnt - Number of addresses in the inbound
source address list.
ppOutDesAddrList - List of outbound destination addresses.
pdwOutDesAddrCnt - Number of addresses in the outbound
destination address list.
ppInDesAddrList - List of inbound destination addresses.
pdwInDesAddrCnt - Number of addresses in the inbound
destination address list.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PADDR pSrcAddrList = NULL;
DWORD dwSrcAddrCnt = 0;
PADDR pDesAddrList = NULL;
DWORD dwDesAddrCnt = 0;
PADDR pOutSrcAddrList = NULL;
DWORD dwOutSrcAddrCnt = 0;
PADDR pInSrcAddrList = NULL;
DWORD dwInSrcAddrCnt = 0;
PADDR pOutDesAddrList = NULL;
DWORD dwOutDesAddrCnt = 0;
PADDR pInDesAddrList = NULL;
DWORD dwInDesAddrCnt = 0;
//
// Replace wild card information to generate the new source
// address list.
//
dwError = FormAddressList(
pFilter->SrcAddr,
pMatchingAddresses,
dwAddrCnt,
&pSrcAddrList,
&dwSrcAddrCnt
);
BAIL_ON_WIN32_ERROR(dwError);
//
// Replace wild card information to generate the new destination
// address list.
//
dwError = FormAddressList(
pFilter->DesAddr,
pMatchingAddresses,
dwAddrCnt,
&pDesAddrList,
&dwDesAddrCnt
);
BAIL_ON_WIN32_ERROR(dwError);
//
// Separate the source address list into outbound and inbound
// source address sets based on the local machine's ip addresses.
//
dwError = SeparateAddrList(
pFilter->SrcAddr.AddrType,
pSrcAddrList,
dwSrcAddrCnt,
pMatchingAddresses,
dwAddrCnt,
&pOutSrcAddrList,
&dwOutSrcAddrCnt,
&pInSrcAddrList,
&dwInSrcAddrCnt
);
BAIL_ON_WIN32_ERROR(dwError);
//
// Separate the destination address list into outbound and inbound
// destination address sets based on the local machine's ip
// addresses.
//
dwError = SeparateAddrList(
pFilter->DesAddr.AddrType,
pDesAddrList,
dwDesAddrCnt,
pMatchingAddresses,
dwAddrCnt,
&pInDesAddrList,
&dwInDesAddrCnt,
&pOutDesAddrList,
&dwOutDesAddrCnt
);
BAIL_ON_WIN32_ERROR(dwError);
*ppOutSrcAddrList = pOutSrcAddrList;
*pdwOutSrcAddrCnt = dwOutSrcAddrCnt;
*ppInSrcAddrList = pInSrcAddrList;
*pdwInSrcAddrCnt = dwInSrcAddrCnt;
*ppOutDesAddrList = pOutDesAddrList;
*pdwOutDesAddrCnt = dwOutDesAddrCnt;
*ppInDesAddrList = pInDesAddrList;
*pdwInDesAddrCnt = dwInDesAddrCnt;
cleanup:
if (pSrcAddrList) {
FreeSPDMemory(pSrcAddrList);
}
if (pDesAddrList) {
FreeSPDMemory(pDesAddrList);
}
return (dwError);
error:
if (pOutSrcAddrList) {
FreeSPDMemory(pOutSrcAddrList);
}
if (pInSrcAddrList) {
FreeSPDMemory(pInSrcAddrList);
}
if (pOutDesAddrList) {
FreeSPDMemory(pOutDesAddrList);
}
if (pInDesAddrList) {
FreeSPDMemory(pInDesAddrList);
}
*ppOutSrcAddrList = NULL;
*pdwOutSrcAddrCnt = 0;
*ppInSrcAddrList = NULL;
*pdwInSrcAddrCnt = 0;
*ppOutDesAddrList = NULL;
*pdwOutDesAddrCnt = 0;
*ppInDesAddrList = NULL;
*pdwInDesAddrCnt = 0;
goto cleanup;
}
DWORD
FormAddressList(
ADDR InAddr,
MATCHING_ADDR * pMatchingAddresses,
DWORD dwAddrCnt,
PADDR * ppOutAddr,
PDWORD pdwOutAddrCnt
)
/*++
Routine Description:
This function forms the address list for a generic
address.
Arguments:
InAddr - Generic address to expand.
pMatchingAddresses - List of local ip addresses whose interface
type matches that of the filter.
dwAddrCnt - Number of local ip addresses in the list.
ppOutAddr - Expanded address list for the generic address.
pdwOutAddrCnt - Number of addresses in the expanded list.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PADDR pOutAddr = NULL;
DWORD dwOutAddrCnt = 0;
DWORD i = 0, j = 0;
switch(InAddr.AddrType) {
case IP_ADDR_UNIQUE:
if (InAddr.uIpAddr == IP_ADDRESS_ME) {
dwError = AllocateSPDMemory(
sizeof(ADDR) * dwAddrCnt,
&pOutAddr
);
BAIL_ON_WIN32_ERROR(dwError);
for (i = 0; i < dwAddrCnt; i++) {
pOutAddr[i].AddrType = InAddr.AddrType;
pOutAddr[i].uIpAddr = pMatchingAddresses[i].uIpAddr;
pOutAddr[i].uSubNetMask = InAddr.uSubNetMask;
memcpy(
&pOutAddr[i].gInterfaceID,
&InAddr.gInterfaceID,
sizeof(GUID)
);
}
dwOutAddrCnt = dwAddrCnt;
}
else {
dwError = AllocateSPDMemory(
sizeof(ADDR),
&pOutAddr
);
BAIL_ON_WIN32_ERROR(dwError);
memcpy(pOutAddr, &InAddr, sizeof(ADDR));
dwOutAddrCnt = 1;
}
break;
case IP_ADDR_SUBNET:
dwError = AllocateSPDMemory(
sizeof(ADDR),
&pOutAddr
);
BAIL_ON_WIN32_ERROR(dwError);
memcpy(pOutAddr, &InAddr, sizeof(ADDR));
dwOutAddrCnt = 1;
break;
case IP_ADDR_INTERFACE:
for (i = 0; i < dwAddrCnt; i++) {
if (!memcmp(
&pMatchingAddresses[i].gInterfaceID,
&InAddr.gInterfaceID,
sizeof(GUID))) {
dwOutAddrCnt++;
}
}
if (dwOutAddrCnt) {
dwError = AllocateSPDMemory(
sizeof(ADDR) * dwOutAddrCnt,
&pOutAddr
);
BAIL_ON_WIN32_ERROR(dwError);
for (i = 0; i < dwAddrCnt; i++) {
if (!memcmp(
&pMatchingAddresses[i].gInterfaceID,
&InAddr.gInterfaceID,
sizeof(GUID))) {
pOutAddr[j].AddrType = InAddr.AddrType;
pOutAddr[j].uIpAddr = pMatchingAddresses[i].uIpAddr;
pOutAddr[j].uSubNetMask = InAddr.uSubNetMask;
memcpy(
&pOutAddr[j].gInterfaceID,
&InAddr.gInterfaceID,
sizeof(GUID)
);
j++;
}
}
}
break;
}
*ppOutAddr = pOutAddr;
*pdwOutAddrCnt = dwOutAddrCnt;
return (dwError);
error:
*ppOutAddr = NULL;
*pdwOutAddrCnt = 0;
return (dwError);
}
DWORD
SeparateAddrList(
ADDR_TYPE AddrType,
PADDR pAddrList,
DWORD dwAddrCnt,
MATCHING_ADDR * pMatchingAddresses,
DWORD dwLocalAddrCnt,
PADDR * ppOutAddrList,
PDWORD pdwOutAddrCnt,
PADDR * ppInAddrList,
PDWORD pdwInAddrCnt
)
/*++
Routine Description:
This function separates the address list into
two mutually exclusive outbound and inbound
address sets.
Arguments:
AddrType - Type of address under consideration.
pAddrList - List of addresses to separate.
dwAddrCnt - Number of addresses in the list.
pMatchingAddresses - List of local ip addresses whose interface
type matches that of the filter.
dwLocalAddrCnt - Number of local ip addresses in the list.
ppOutAddrList - List of outbound addresses.
pdwOutAddrCnt - Number of addresses in the outbound
address list.
ppInAddrList - List of inbound addresses.
pdwInAddrCnt - Number of addresses in the inbound
address list.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
switch(AddrType) {
case IP_ADDR_UNIQUE:
dwError = SeparateUniqueAddresses(
pAddrList,
dwAddrCnt,
pMatchingAddresses,
dwLocalAddrCnt,
ppOutAddrList,
pdwOutAddrCnt,
ppInAddrList,
pdwInAddrCnt
);
BAIL_ON_WIN32_ERROR(dwError);
break;
case IP_ADDR_SUBNET:
dwError = SeparateSubNetAddresses(
pAddrList,
dwAddrCnt,
pMatchingAddresses,
dwLocalAddrCnt,
ppOutAddrList,
pdwOutAddrCnt,
ppInAddrList,
pdwInAddrCnt
);
BAIL_ON_WIN32_ERROR(dwError);
break;
case IP_ADDR_INTERFACE:
dwError = SeparateInterfaceAddresses(
pAddrList,
dwAddrCnt,
pMatchingAddresses,
dwLocalAddrCnt,
ppOutAddrList,
pdwOutAddrCnt,
ppInAddrList,
pdwInAddrCnt
);
BAIL_ON_WIN32_ERROR(dwError);
break;
}
error:
return (dwError);
}
DWORD
FormSpecificTxFilters(
PINITXFILTER pFilter,
PADDR pSrcAddrList,
DWORD dwSrcAddrCnt,
PADDR pDesAddrList,
DWORD dwDesAddrCnt,
DWORD dwDirection,
PINITXSFILTER * ppSpecificFilters
)
/*++
Routine Description:
This function forms the specific transport filters
for the given generic filter and the source and
destination address sets.
Arguments:
pFilter - Generic filter for which specific filters
are to be created.
pSrcAddrList - List of source addresses.
dwSrcAddrCnt - Number of addresses in the source
address list.
pDesAddrList - List of destination addresses.
dwDesAddrCnt - Number of addresses in the destination
address list.
ppSpecificFilters - Specific filters created for the given
generic filter and the given addresses.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PINITXSFILTER pSpecificFilters = NULL;
DWORD i = 0, j = 0;
PINITXSFILTER pSpecificFilter = NULL;
for (i = 0; i < dwSrcAddrCnt; i++) {
for (j = 0; j < dwDesAddrCnt; j++) {
dwError = CreateSpecificTxFilter(
pFilter,
pSrcAddrList[i],
pDesAddrList[j],
&pSpecificFilter
);
BAIL_ON_WIN32_ERROR(dwError);
//
// Set the direction of the filter.
//
pSpecificFilter->dwDirection = dwDirection;
AssignTxFilterWeight(pSpecificFilter);
AddToSpecificTxList(
&pSpecificFilters,
pSpecificFilter
);
}
}
*ppSpecificFilters = pSpecificFilters;
return (dwError);
error:
if (pSpecificFilters) {
FreeIniTxSFilterList(pSpecificFilters);
}
*ppSpecificFilters = NULL;
return (dwError);
}
DWORD
SeparateUniqueAddresses(
PADDR pAddrList,
DWORD dwAddrCnt,
MATCHING_ADDR * pMatchingAddresses,
DWORD dwLocalAddrCnt,
PADDR * ppIsMeAddrList,
PDWORD pdwIsMeAddrCnt,
PADDR * ppIsNotMeAddrList,
PDWORD pdwIsNotMeAddrCnt
)
/*++
Routine Description:
This function separates a list of unique ip addresses into
two mutually exclusive local and non-local address sets.
Arguments:
pAddrList - List of unique ip addresses to separate.
dwAddrCnt - Number of unique ip addresses in the list.
pMatchingAddresses - List of local ip addresses whose interface
type matches that of the filter.
dwAddrCnt - Number of local ip addresses in the list.
ppIsMeAddrList - List of machine's ip addresses separated from
the given list.
pdwIsMeAddrCnt - Number of machine's ip addresses in the list.
ppIsNotMeAddrList - List of not machine's ip addresses separated from
the given list.
pdwIsNotMeAddrCnt - Number of not machine's ip addresses in the list.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PADDR pIsMeAddrList = NULL;
DWORD dwIsMeAddrCnt = 0;
PADDR pIsNotMeAddrList = NULL;
DWORD dwIsNotMeAddrCnt = 0;
DWORD i = 0, j = 0, k = 0;
BOOL bEqual = FALSE;
BOOL bIsClassD = FALSE;
for (i = 0; i < dwAddrCnt; i++) {
bIsClassD = IN_CLASSD(ntohl(pAddrList[i].uIpAddr));
switch (bIsClassD) {
case TRUE:
dwIsMeAddrCnt++;
dwIsNotMeAddrCnt++;
break;
case FALSE:
//
// Check if the address is one of the matching interfaces' address.
//
bEqual = InterfaceAddrIsLocal(
pAddrList[i].uIpAddr,
pAddrList[i].uSubNetMask,
pMatchingAddresses,
dwLocalAddrCnt
);
if (bEqual) {
dwIsMeAddrCnt++;
}
else {
//
// Check if the address is one of the machine's ip address.
//
bEqual = IsMyAddress(
pAddrList[i].uIpAddr,
pAddrList[i].uSubNetMask,
gpInterfaceList
);
if (!bEqual) {
dwIsNotMeAddrCnt++;
}
}
break;
}
}
if (dwIsMeAddrCnt) {
dwError = AllocateSPDMemory(
sizeof(ADDR) * dwIsMeAddrCnt,
&pIsMeAddrList
);
BAIL_ON_WIN32_ERROR(dwError);
}
if (dwIsNotMeAddrCnt) {
dwError = AllocateSPDMemory(
sizeof(ADDR) * dwIsNotMeAddrCnt,
&pIsNotMeAddrList
);
BAIL_ON_WIN32_ERROR(dwError);
}
for (i = 0; i < dwAddrCnt; i++) {
bIsClassD = IN_CLASSD(ntohl(pAddrList[i].uIpAddr));
switch (bIsClassD) {
case TRUE:
memcpy(
&(pIsMeAddrList[j]),
&(pAddrList[i]),
sizeof(ADDR)
);
j++;
memcpy(
&pIsNotMeAddrList[k],
&pAddrList[i],
sizeof(ADDR)
);
k++;
break;
case FALSE:
bEqual = InterfaceAddrIsLocal(
pAddrList[i].uIpAddr,
pAddrList[i].uSubNetMask,
pMatchingAddresses,
dwLocalAddrCnt
);
if (bEqual) {
memcpy(
&(pIsMeAddrList[j]),
&(pAddrList[i]),
sizeof(ADDR)
);
j++;
}
else {
bEqual = IsMyAddress(
pAddrList[i].uIpAddr,
pAddrList[i].uSubNetMask,
gpInterfaceList
);
if (!bEqual) {
memcpy(
&pIsNotMeAddrList[k],
&pAddrList[i],
sizeof(ADDR)
);
k++;
}
}
break;
}
}
*ppIsMeAddrList = pIsMeAddrList;
*pdwIsMeAddrCnt = dwIsMeAddrCnt;
*ppIsNotMeAddrList = pIsNotMeAddrList;
*pdwIsNotMeAddrCnt = dwIsNotMeAddrCnt;
return (dwError);
error:
if (pIsMeAddrList) {
FreeSPDMemory(pIsMeAddrList);
}
if (pIsNotMeAddrList) {
FreeSPDMemory(pIsNotMeAddrList);
}
*ppIsMeAddrList = NULL;
*pdwIsMeAddrCnt = 0;
*ppIsNotMeAddrList = NULL;
*pdwIsNotMeAddrCnt = 0;
return (dwError);
}
DWORD
SeparateSubNetAddresses(
PADDR pAddrList,
DWORD dwAddrCnt,
MATCHING_ADDR * pMatchingAddresses,
DWORD dwLocalAddrCnt,
PADDR * ppIsMeAddrList,
PDWORD pdwIsMeAddrCnt,
PADDR * ppIsNotMeAddrList,
PDWORD pdwIsNotMeAddrCnt
)
/*++
Routine Description:
This function separates a list of subnet addresses into
two non-mutually exclusive local and non-local address sets.
Arguments:
pAddrList - List of subnet addresses to separate.
dwAddrCnt - Number of subnet addresses in the list.
pMatchingAddresses - List of local ip addresses whose interface
type matches that of the filter.
dwAddrCnt - Number of local ip addresses in the list.
ppIsMeAddrList - List of subnet addresses that contain atleast
one of the machine's ip address.
pdwIsMeAddrCnt - Number of subnet addresses containing atleast
one of the machine's ip address.
ppIsNotMeAddrList - List of subnet addresses as in the input list.
pdwIsNotMeAddrCnt - Number of subnet addresses as in the input list.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
PADDR pIsMeAddrList = NULL;
DWORD dwIsMeAddrCnt = 0;
PADDR pIsNotMeAddrList = NULL;
DWORD dwIsNotMeAddrCnt = 0;
DWORD i = 0, j = 0, k = 0;
BOOL bEqual = FALSE;
BOOL bIsClassD = FALSE;
for (i = 0; i < dwAddrCnt; i++) {
bIsClassD = IN_CLASSD(ntohl(pAddrList[i].uIpAddr));
switch (bIsClassD) {
case TRUE:
dwIsMeAddrCnt++;
break;
case FALSE:
//
// Check if one of the matching interfaces' address belongs to
// the subnet.
//
bEqual = InterfaceAddrIsLocal(
pAddrList[i].uIpAddr,
pAddrList[i].uSubNetMask,
pMatchingAddresses,
dwLocalAddrCnt
);
if (bEqual) {
dwIsMeAddrCnt++;
}
break;
}
//
// The subnet will have addresses that don't belong to the local
// machine.
//
dwIsNotMeAddrCnt++;
}
if (dwIsMeAddrCnt) {
dwError = AllocateSPDMemory(
sizeof(ADDR) * dwIsMeAddrCnt,
&pIsMeAddrList
);
BAIL_ON_WIN32_ERROR(dwError);
}
if (dwIsNotMeAddrCnt) {
dwError = AllocateSPDMemory(
sizeof(ADDR) * dwIsNotMeAddrCnt,
&pIsNotMeAddrList
);
BAIL_ON_WIN32_ERROR(dwError);
}
for (i = 0; i < dwAddrCnt; i++) {
bIsClassD = IN_CLASSD(ntohl(pAddrList[i].uIpAddr));
switch (bIsClassD) {
case TRUE:
memcpy(
&(pIsMeAddrList[j]),
&(pAddrList[i]),
sizeof(ADDR)
);
j++;
break;
case FALSE:
bEqual = InterfaceAddrIsLocal(
pAddrList[i].uIpAddr,
pAddrList[i].uSubNetMask,
pMatchingAddresses,
dwLocalAddrCnt
);
if (bEqual) {
memcpy(
&(pIsMeAddrList[j]),
&(pAddrList[i]),
sizeof(ADDR)
);
j++;
}
break;
}
memcpy(
&pIsNotMeAddrList[k],
&pAddrList[i],
sizeof(ADDR)
);
k++;
}
*ppIsMeAddrList = pIsMeAddrList;
*pdwIsMeAddrCnt = dwIsMeAddrCnt;
*ppIsNotMeAddrList = pIsNotMeAddrList;
*pdwIsNotMeAddrCnt = dwIsNotMeAddrCnt;
return (dwError);
error:
if (pIsMeAddrList) {
FreeSPDMemory(pIsMeAddrList);
}
if (pIsNotMeAddrList) {
FreeSPDMemory(pIsNotMeAddrList);
}
*ppIsMeAddrList = NULL;
*pdwIsMeAddrCnt = 0;
*ppIsNotMeAddrList = NULL;
*pdwIsNotMeAddrCnt = 0;
return (dwError);
}
DWORD
CreateSpecificTxFilter(
PINITXFILTER pGenericFilter,
ADDR SrcAddr,
ADDR DesAddr,
PINITXSFILTER * ppSpecificFilter
)
{
DWORD dwError = 0;
PINITXSFILTER pSpecificFilter = NULL;
dwError = AllocateSPDMemory(
sizeof(INITXSFILTER),
&pSpecificFilter
);
BAIL_ON_WIN32_ERROR(dwError);
pSpecificFilter->cRef = 0;
CopyGuid(pGenericFilter->gFilterID, &(pSpecificFilter->gParentID));
dwError = AllocateSPDString(
pGenericFilter->pszFilterName,
&(pSpecificFilter->pszFilterName)
);
BAIL_ON_WIN32_ERROR(dwError);
pSpecificFilter->InterfaceType = pGenericFilter->InterfaceType;
pSpecificFilter->dwFlags = pGenericFilter->dwFlags;
CopyAddresses(SrcAddr, &(pSpecificFilter->SrcAddr));
CopyAddresses(DesAddr, &(pSpecificFilter->DesAddr));
CopyPorts(pGenericFilter->SrcPort, &(pSpecificFilter->SrcPort));
CopyPorts(pGenericFilter->DesPort, &(pSpecificFilter->DesPort));
CopyProtocols(pGenericFilter->Protocol, &(pSpecificFilter->Protocol));
pSpecificFilter->InboundFilterFlag = pGenericFilter->InboundFilterFlag;
pSpecificFilter->OutboundFilterFlag = pGenericFilter->OutboundFilterFlag;
//
// Direction must be set in the calling routine.
//
pSpecificFilter->dwDirection = 0;
//
// Weight must be set in the calling routine.
//
pSpecificFilter->dwWeight = 0;
CopyGuid(pGenericFilter->gPolicyID, &(pSpecificFilter->gPolicyID));
pSpecificFilter->pIniQMPolicy = NULL;
pSpecificFilter->pNext = NULL;
*ppSpecificFilter = pSpecificFilter;
return (dwError);
error:
if (pSpecificFilter) {
FreeIniTxSFilter(pSpecificFilter);
}
*ppSpecificFilter = NULL;
return (dwError);
}
VOID
AssignTxFilterWeight(
PINITXSFILTER pSpecificFilter
)
/*++
Routine Description:
Computes and assigns the weight to a specific transport filter.
The transport filter weight consists of the following:
31 16 12 8 0
+-----------+--------+-----------+--------+
|AddrMaskWgt|Reserved|ProtocolWgt|PortWgts|
+-----------+--------+-----------+--------+
Arguments:
pSpecificFilter - Specific transport filter to which the weight
is to be assigned.
Return Value:
None.
--*/
{
DWORD dwWeight = 0;
ULONG SrcMask = 0;
ULONG DesMask = 0;
DWORD dwMaskWeight = 0;
DWORD i = 0;
//
// Weight Rule:
// A field with a more specific value gets a higher weight than
// the same field with a lesser specific value.
//
//
// If the protocol is specific then assign the specific protocol
// weight else the weight is zero.
// All the specific filters that have a specific protocol and
// differ only in the protocol field will have the same weight.
//
if (pSpecificFilter->Protocol.dwProtocol != 0) {
dwWeight |= WEIGHT_SPECIFIC_PROTOCOL;
}
//
// If the source port is specific then assign the specific source
// port weight else the weight is zero.
// All the specific filters that have a specific source port and
// differ only in the source port field will have the same weight.
//
if (pSpecificFilter->SrcPort.wPort != 0) {
dwWeight |= WEIGHT_SPECIFIC_SOURCE_PORT;
}
//
// If the destination port is specific then assign the specific
// destination port weight else the weight is zero.
// All the specific filters that have a specific destination port
// and differ only in the destination port field will have the
// same weight.
//
if (pSpecificFilter->DesPort.wPort != 0) {
dwWeight |= WEIGHT_SPECIFIC_DESTINATION_PORT;
}
//
// IP addresses get the weight values based on their mask values.
// In the address case, the weight is computed as a sum of the
// bit positions starting from the position that contains the
// first least significant non-zero bit to the most significant
// bit position of the mask.
// All unique ip addresses have a mask of 0xFFFFFFFF and thus get
// the same weight, which is 1 + 2 + .... + 32.
// A subnet address has a mask with atleast the least significant
// bit zero and thus gets weight in the range (2 + .. + 32) to 0.
//
DesMask = ntohl(pSpecificFilter->DesAddr.uSubNetMask);
for (i = 0; i < sizeof(ULONG) * 8; i++) {
//
// If the bit position contains a non-zero bit, add the bit
// position to the sum.
//
if ((DesMask & 0x1) == 0x1) {
dwMaskWeight += (i+1);
}
//
// Move to the next bit position.
//
DesMask = DesMask >> 1;
}
SrcMask = ntohl(pSpecificFilter->SrcAddr.uSubNetMask);
for (i = 0; i < sizeof(ULONG) * 8; i++) {
//
// If the bit position contains a non-zero bit, add the bit
// position to the sum.
//
if ((SrcMask & 0x1) == 0x1) {
dwMaskWeight += (i+1);
}
//
// Move to the next bit position.
//
SrcMask = SrcMask >> 1;
}
//
// Move the mask weight to the set of bits in the overall weight
// that it occupies.
//
dwMaskWeight = dwMaskWeight << 16;
dwWeight += dwMaskWeight;
pSpecificFilter->dwWeight = dwWeight;
}
VOID
AddToSpecificTxList(
PINITXSFILTER * ppSpecificTxFilterList,
PINITXSFILTER pSpecificTxFilters
)
{
PINITXSFILTER pListOne = NULL;
PINITXSFILTER pListTwo = NULL;
PINITXSFILTER pListMerge = NULL;
PINITXSFILTER pLast = NULL;
if (!(*ppSpecificTxFilterList) && !pSpecificTxFilters) {
return;
}
if (!(*ppSpecificTxFilterList)) {
*ppSpecificTxFilterList = pSpecificTxFilters;
return;
}
if (!pSpecificTxFilters) {
return;
}
pListOne = *ppSpecificTxFilterList;
pListTwo = pSpecificTxFilters;
while (pListOne && pListTwo) {
if ((pListOne->dwWeight) > (pListTwo->dwWeight)) {
if (!pListMerge) {
pListMerge = pListOne;
pLast = pListOne;
pListOne = pListOne->pNext;
}
else {
pLast->pNext = pListOne;
pListOne = pListOne->pNext;
pLast = pLast->pNext;
}
}
else {
if (!pListMerge) {
pListMerge = pListTwo;
pLast = pListTwo;
pListTwo = pListTwo->pNext;
}
else {
pLast->pNext = pListTwo;
pListTwo = pListTwo->pNext;
pLast = pLast->pNext;
}
}
}
if (pListOne) {
pLast->pNext = pListOne;
}
else {
pLast->pNext = pListTwo;
}
*ppSpecificTxFilterList = pListMerge;
return;
}
VOID
FreeIniTxSFilterList(
PINITXSFILTER pIniTxSFilterList
)
{
PINITXSFILTER pFilter = NULL;
PINITXSFILTER pTempFilter = NULL;
pFilter = pIniTxSFilterList;
while (pFilter) {
pTempFilter = pFilter;
pFilter = pFilter->pNext;
FreeIniTxSFilter(pTempFilter);
}
}
VOID
FreeIniTxSFilter(
PINITXSFILTER pIniTxSFilter
)
{
if (pIniTxSFilter) {
if (pIniTxSFilter->pszFilterName) {
FreeSPDString(pIniTxSFilter->pszFilterName);
}
//
// Must not ever free pIniTxSFilter->pIniQMPolicy.
//
FreeSPDMemory(pIniTxSFilter);
}
}
VOID
LinkTxSpecificFilters(
PINIQMPOLICY pIniQMPolicy,
PINITXSFILTER pIniTxSFilters
)
{
PINITXSFILTER pTemp = NULL;
pTemp = pIniTxSFilters;
while (pTemp) {
pTemp->pIniQMPolicy = pIniQMPolicy;
pTemp = pTemp->pNext;
}
return;
}
VOID
RemoveIniTxSFilter(
PINITXSFILTER pIniTxSFilter
)
{
PINITXSFILTER * ppTemp = NULL;
ppTemp = &gpIniTxSFilter;
while (*ppTemp) {
if (*ppTemp == pIniTxSFilter) {
break;
}
ppTemp = &((*ppTemp)->pNext);
}
if (*ppTemp) {
*ppTemp = pIniTxSFilter->pNext;
}
return;
}
DWORD
EnumSpecificTxFilters(
PINITXSFILTER pIniTxSFilterList,
DWORD dwResumeHandle,
DWORD dwPreferredNumEntries,
PTRANSPORT_FILTER * ppTxFilters,
PDWORD pdwNumTxFilters
)
/*++
Routine Description:
This function creates enumerated specific filters.
Arguments:
pIniTxSFilterList - List of specific filters to enumerate.
dwResumeHandle - Location in the specific filter list from which
to resume enumeration.
dwPreferredNumEntries - Preferred number of enumeration entries.
ppTxFilters - Enumerated filters returned to the caller.
pdwNumTxFilters - Number of filters actually enumerated.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
DWORD dwNumToEnum = 0;
PINITXSFILTER pIniTxSFilter = NULL;
DWORD i = 0;
PINITXSFILTER pTemp = NULL;
DWORD dwNumTxFilters = 0;
PTRANSPORT_FILTER pTxFilters = 0;
PTRANSPORT_FILTER pTxFilter = 0;
if (!dwPreferredNumEntries ||
(dwPreferredNumEntries > MAX_TRANSPORTFILTER_ENUM_COUNT)) {
dwNumToEnum = MAX_TRANSPORTFILTER_ENUM_COUNT;
}
else {
dwNumToEnum = dwPreferredNumEntries;
}
pIniTxSFilter = pIniTxSFilterList;
for (i = 0; (i < dwResumeHandle) && (pIniTxSFilter != NULL); i++) {
pIniTxSFilter = pIniTxSFilter->pNext;
}
if (!pIniTxSFilter) {
dwError = ERROR_NO_DATA;
BAIL_ON_WIN32_ERROR(dwError);
}
pTemp = pIniTxSFilter;
while (pTemp && (dwNumTxFilters < dwNumToEnum)) {
dwNumTxFilters++;
pTemp = pTemp->pNext;
}
dwError = SPDApiBufferAllocate(
sizeof(TRANSPORT_FILTER)*dwNumTxFilters,
&pTxFilters
);
BAIL_ON_WIN32_ERROR(dwError);
pTemp = pIniTxSFilter;
pTxFilter = pTxFilters;
for (i = 0; i < dwNumTxFilters; i++) {
dwError = CopyTxSFilter(
pTemp,
pTxFilter
);
BAIL_ON_WIN32_ERROR(dwError);
pTemp = pTemp->pNext;
pTxFilter++;
}
*ppTxFilters = pTxFilters;
*pdwNumTxFilters = dwNumTxFilters;
return (dwError);
error:
if (pTxFilters) {
FreeTxFilters(
i,
pTxFilters
);
}
*ppTxFilters = NULL;
*pdwNumTxFilters = 0;
return (dwError);
}
DWORD
CopyTxSFilter(
PINITXSFILTER pIniTxSFilter,
PTRANSPORT_FILTER pTxFilter
)
/*++
Routine Description:
This function copies an internal filter into an external filter
container.
Arguments:
pIniTxSFilter - Internal filter to copy.
pTxFilter - External filter container in which to copy.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
CopyGuid(pIniTxSFilter->gParentID, &(pTxFilter->gFilterID));
dwError = CopyName(
pIniTxSFilter->pszFilterName,
&(pTxFilter->pszFilterName)
);
BAIL_ON_WIN32_ERROR(dwError);
pTxFilter->InterfaceType = pIniTxSFilter->InterfaceType;
pTxFilter->bCreateMirror = FALSE;
pTxFilter->dwFlags = pIniTxSFilter->dwFlags;
CopyAddresses(pIniTxSFilter->SrcAddr, &(pTxFilter->SrcAddr));
CopyAddresses(pIniTxSFilter->DesAddr, &(pTxFilter->DesAddr));
CopyProtocols(pIniTxSFilter->Protocol, &(pTxFilter->Protocol));
CopyPorts(pIniTxSFilter->SrcPort, &(pTxFilter->SrcPort));
CopyPorts(pIniTxSFilter->DesPort, &(pTxFilter->DesPort));
pTxFilter->InboundFilterFlag = pIniTxSFilter->InboundFilterFlag;
pTxFilter->OutboundFilterFlag = pIniTxSFilter->OutboundFilterFlag;
pTxFilter->dwDirection = pIniTxSFilter->dwDirection;
pTxFilter->dwWeight = pIniTxSFilter->dwWeight;
CopyGuid(pIniTxSFilter->gPolicyID, &(pTxFilter->gPolicyID));
error:
return (dwError);
}
DWORD
EnumSelectSpecificTxFilters(
PINITXFILTER pIniTxFilter,
DWORD dwResumeHandle,
DWORD dwPreferredNumEntries,
PTRANSPORT_FILTER * ppTxFilters,
PDWORD pdwNumTxFilters
)
/*++
Routine Description:
This function creates enumerated specific filters for
the given generic filter.
Arguments:
pIniTxFilter - Generic filter for which specific filters
are to be enumerated.
dwResumeHandle - Location in the specific filter list for the
given generic filter from which to resume
enumeration.
dwPreferredNumEntries - Preferred number of enumeration entries.
ppTxFilters - Enumerated filters returned to the caller.
pdwNumTxFilters - Number of filters actually enumerated.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
DWORD dwNumToEnum = 0;
DWORD dwNumTxSFilters = 0;
PINITXSFILTER * ppIniTxSFilters = NULL;
DWORD i = 0;
DWORD dwNumTxFilters = 0;
PTRANSPORT_FILTER pTxFilters = 0;
PTRANSPORT_FILTER pTxFilter = 0;
if (!dwPreferredNumEntries ||
(dwPreferredNumEntries > MAX_TRANSPORTFILTER_ENUM_COUNT)) {
dwNumToEnum = MAX_TRANSPORTFILTER_ENUM_COUNT;
}
else {
dwNumToEnum = dwPreferredNumEntries;
}
dwNumTxSFilters = pIniTxFilter->dwNumTxSFilters;
ppIniTxSFilters = pIniTxFilter->ppIniTxSFilters;
if (!dwNumTxSFilters || (dwNumTxSFilters <= dwResumeHandle)) {
dwError = ERROR_NO_DATA;
BAIL_ON_WIN32_ERROR(dwError);
}
dwNumTxFilters = min((dwNumTxSFilters-dwResumeHandle),
dwNumToEnum);
dwError = SPDApiBufferAllocate(
sizeof(TRANSPORT_FILTER)*dwNumTxFilters,
&pTxFilters
);
BAIL_ON_WIN32_ERROR(dwError);
pTxFilter = pTxFilters;
for (i = 0; i < dwNumTxFilters; i++) {
dwError = CopyTxSFilter(
*(ppIniTxSFilters + (dwResumeHandle + i)),
pTxFilter
);
BAIL_ON_WIN32_ERROR(dwError);
pTxFilter++;
}
*ppTxFilters = pTxFilters;
*pdwNumTxFilters = dwNumTxFilters;
return (dwError);
error:
if (pTxFilters) {
FreeTxFilters(
i,
pTxFilters
);
}
*ppTxFilters = NULL;
*pdwNumTxFilters = 0;
return (dwError);
}
DWORD
MatchTransportFilter(
LPWSTR pServerName,
PTRANSPORT_FILTER pTxFilter,
DWORD dwFlags,
PTRANSPORT_FILTER * ppMatchedTxFilters,
PIPSEC_QM_POLICY * ppMatchedQMPolicies,
DWORD dwPreferredNumEntries,
LPDWORD pdwNumMatches,
LPDWORD pdwResumeHandle
)
/*++
Routine Description:
This function finds the matching transport filters for the
given transport filter template. The matched filters can not
be more specific than the given filter template.
Arguments:
pServerName - Server on which a filter template is to be matched.
pTxFilter - Filter template to match.
dwFlags - Flags.
ppMatchedTxFilters - Matched transport filters returned to the
caller.
ppMatchedQMPolicies - Quick mode policies corresponding to the
matched transport filters returned to the
caller.
dwPreferredNumEntries - Preferred number of matched entries.
pdwNumMatches - Number of filters actually matched.
pdwResumeHandle - Handle to the location in the matched filter
list from which to resume enumeration.
Return Value:
ERROR_SUCCESS - Success.
Win32 Error - Failure.
--*/
{
DWORD dwError = 0;
DWORD dwResumeHandle = 0;
DWORD dwNumToMatch = 0;
PINITXSFILTER pIniTxSFilter = NULL;
DWORD i = 0;
BOOL bMatches = FALSE;
PINITXSFILTER pTemp = NULL;
DWORD dwNumMatches = 0;
PINITXSFILTER pLastMatchedFilter = NULL;
PTRANSPORT_FILTER pMatchedTxFilters = NULL;
PIPSEC_QM_POLICY pMatchedQMPolicies = NULL;
DWORD dwNumFilters = 0;
DWORD dwNumPolicies = 0;
PTRANSPORT_FILTER pMatchedTxFilter = NULL;
PIPSEC_QM_POLICY pMatchedQMPolicy = NULL;
dwError = ValidateTxFilterTemplate(
pTxFilter
);
BAIL_ON_WIN32_ERROR(dwError);
dwResumeHandle = *pdwResumeHandle;
if (!dwPreferredNumEntries) {
dwNumToMatch = 1;
}
else if (dwPreferredNumEntries > MAX_TRANSPORTFILTER_ENUM_COUNT) {
dwNumToMatch = MAX_TRANSPORTFILTER_ENUM_COUNT;
}
else {
dwNumToMatch = dwPreferredNumEntries;
}
ENTER_SPD_SECTION();
dwError = ValidateTxSecurity(
SPD_OBJECT_SERVER,
SERVER_ACCESS_ADMINISTER,
NULL,
NULL
);
BAIL_ON_LOCK_ERROR(dwError);
pIniTxSFilter = gpIniTxSFilter;
while ((i < dwResumeHandle) && (pIniTxSFilter != NULL)) {
bMatches = MatchIniTxSFilter(
pIniTxSFilter,
pTxFilter
);
if (bMatches) {
i++;
}
pIniTxSFilter = pIniTxSFilter->pNext;
}
if (!pIniTxSFilter) {
if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) {
dwError = ERROR_NO_DATA;
BAIL_ON_LOCK_ERROR(dwError);
}
else {
dwError = CopyTxMatchDefaults(
&pMatchedTxFilters,
&pMatchedQMPolicies,
&dwNumMatches
);
BAIL_ON_LOCK_ERROR(dwError);
BAIL_ON_LOCK_SUCCESS(dwError);
}
}
pTemp = pIniTxSFilter;
while (pTemp && (dwNumMatches < dwNumToMatch)) {
bMatches = MatchIniTxSFilter(
pTemp,
pTxFilter
);
if (bMatches) {
pLastMatchedFilter = pTemp;
dwNumMatches++;
}
pTemp = pTemp->pNext;
}
if (!dwNumMatches) {
if (!(dwFlags & RETURN_DEFAULTS_ON_NO_MATCH)) {
dwError = ERROR_NO_DATA;
BAIL_ON_LOCK_ERROR(dwError);
}
else {
dwError = CopyTxMatchDefaults(
&pMatchedTxFilters,
&pMatchedQMPolicies,
&dwNumMatches
);
BAIL_ON_LOCK_ERROR(dwError);
BAIL_ON_LOCK_SUCCESS(dwError);
}
}
dwError = SPDApiBufferAllocate(
sizeof(TRANSPORT_FILTER)*dwNumMatches,
&pMatchedTxFilters
);
BAIL_ON_LOCK_ERROR(dwError);
dwError = SPDApiBufferAllocate(
sizeof(IPSEC_QM_POLICY)*dwNumMatches,
&pMatchedQMPolicies
);
BAIL_ON_LOCK_ERROR(dwError);
if (dwNumMatches == 1) {
dwError = CopyTxSFilter(
pLastMatchedFilter,
pMatchedTxFilters
);
BAIL_ON_LOCK_ERROR(dwError);
dwNumFilters++;
if (pLastMatchedFilter->pIniQMPolicy) {
dwError = CopyQMPolicy(
pLastMatchedFilter->pIniQMPolicy,
pMatchedQMPolicies
);
BAIL_ON_LOCK_ERROR(dwError);
}
else {
memset(pMatchedQMPolicies, 0, sizeof(IPSEC_QM_POLICY));
}
dwNumPolicies++;
}
else {
pTemp = pIniTxSFilter;
pMatchedTxFilter = pMatchedTxFilters;
pMatchedQMPolicy = pMatchedQMPolicies;
i = 0;
while (i < dwNumMatches) {
bMatches = MatchIniTxSFilter(
pTemp,
pTxFilter
);
if (bMatches) {
dwError = CopyTxSFilter(
pTemp,
pMatchedTxFilter
);
BAIL_ON_LOCK_ERROR(dwError);
pMatchedTxFilter++;
dwNumFilters++;
if (pTemp->pIniQMPolicy) {
dwError = CopyQMPolicy(
pTemp->pIniQMPolicy,
pMatchedQMPolicy
);
BAIL_ON_LOCK_ERROR(dwError);
}
else {
memset(pMatchedQMPolicy, 0, sizeof(IPSEC_QM_POLICY));
}
pMatchedQMPolicy++;
dwNumPolicies++;
i++;
}
pTemp = pTemp->pNext;
}
}
lock_success:
LEAVE_SPD_SECTION();
*ppMatchedTxFilters = pMatchedTxFilters;
*ppMatchedQMPolicies = pMatchedQMPolicies;
*pdwNumMatches = dwNumMatches;
*pdwResumeHandle = dwResumeHandle + dwNumMatches;
return (dwError);
lock:
LEAVE_SPD_SECTION();
error:
if (pMatchedTxFilters) {
FreeTxFilters(
dwNumFilters,
pMatchedTxFilters
);
}
if (pMatchedQMPolicies) {
FreeQMPolicies(
dwNumPolicies,
pMatchedQMPolicies
);
}
*ppMatchedTxFilters = NULL;
*ppMatchedQMPolicies = NULL;
*pdwNumMatches = 0;
*pdwResumeHandle = dwResumeHandle;
return (dwError);
}
DWORD
ValidateTxFilterTemplate(
PTRANSPORT_FILTER pTxFilter
)
{
DWORD dwError = 0;
BOOL bConflicts = FALSE;
if (!pTxFilter) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
dwError = VerifyAddresses(pTxFilter->SrcAddr, TRUE, FALSE);
BAIL_ON_WIN32_ERROR(dwError);
dwError = VerifyAddresses(pTxFilter->DesAddr, TRUE, TRUE);
BAIL_ON_WIN32_ERROR(dwError);
bConflicts = AddressesConflict(
pTxFilter->SrcAddr,
pTxFilter->DesAddr
);
if (bConflicts) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
dwError = VerifyProtocols(pTxFilter->Protocol);
BAIL_ON_WIN32_ERROR(dwError);
dwError = VerifyPortsForProtocol(
pTxFilter->SrcPort,
pTxFilter->Protocol
);
BAIL_ON_WIN32_ERROR(dwError);
dwError = VerifyPortsForProtocol(
pTxFilter->DesPort,
pTxFilter->Protocol
);
BAIL_ON_WIN32_ERROR(dwError);
if (pTxFilter->dwDirection) {
if ((pTxFilter->dwDirection != FILTER_DIRECTION_INBOUND) &&
(pTxFilter->dwDirection != FILTER_DIRECTION_OUTBOUND)) {
dwError = ERROR_INVALID_PARAMETER;
BAIL_ON_WIN32_ERROR(dwError);
}
}
error:
return (dwError);
}
BOOL
MatchIniTxSFilter(
PINITXSFILTER pIniTxSFilter,
PTRANSPORT_FILTER pTxFilter
)
{
BOOL bMatches = FALSE;
if (pTxFilter->dwDirection) {
if (pTxFilter->dwDirection != pIniTxSFilter->dwDirection) {
return (FALSE);
}
}
if ((pIniTxSFilter->InboundFilterFlag != NEGOTIATE_SECURITY) &&
(pIniTxSFilter->OutboundFilterFlag != NEGOTIATE_SECURITY)) {
return (FALSE);
}
bMatches = MatchAddresses(
pIniTxSFilter->SrcAddr,
pTxFilter->SrcAddr
);
if (!bMatches) {
return (FALSE);
}
bMatches = MatchAddresses(
pIniTxSFilter->DesAddr,
pTxFilter->DesAddr
);
if (!bMatches) {
return (FALSE);
}
bMatches = MatchPorts(
pIniTxSFilter->SrcPort,
pTxFilter->SrcPort
);
if (!bMatches) {
return (FALSE);
}
bMatches = MatchPorts(
pIniTxSFilter->DesPort,
pTxFilter->DesPort
);
if (!bMatches) {
return (FALSE);
}
bMatches = MatchProtocols(
pIniTxSFilter->Protocol,
pTxFilter->Protocol
);
if (!bMatches) {
return (FALSE);
}
return (TRUE);
}
DWORD
CopyTxMatchDefaults(
PTRANSPORT_FILTER * ppTxFilters,
PIPSEC_QM_POLICY * ppQMPolicies,
PDWORD pdwNumMatches
)
{
DWORD dwError = 0;
PTRANSPORT_FILTER pTxFilters = NULL;
PIPSEC_QM_POLICY pQMPolicies = NULL;
DWORD dwNumFilters = 0;
DWORD dwNumPolicies = 0;
if (!gpIniDefaultQMPolicy) {
dwError = ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND;
BAIL_ON_WIN32_ERROR(dwError);
}
dwError = SPDApiBufferAllocate(
sizeof(TRANSPORT_FILTER),
&pTxFilters
);
BAIL_ON_WIN32_ERROR(dwError);
dwError = SPDApiBufferAllocate(
sizeof(IPSEC_QM_POLICY),
&pQMPolicies
);
BAIL_ON_WIN32_ERROR(dwError);
dwError = CopyDefaultTxFilter(
pTxFilters,
gpIniDefaultQMPolicy
);
BAIL_ON_WIN32_ERROR(dwError);
dwNumFilters++;
dwError = CopyQMPolicy(
gpIniDefaultQMPolicy,
pQMPolicies
);
BAIL_ON_WIN32_ERROR(dwError);
pQMPolicies->dwFlags |= IPSEC_QM_POLICY_ON_NO_MATCH;
dwNumPolicies++;
*ppTxFilters = pTxFilters;
*ppQMPolicies = pQMPolicies;
*pdwNumMatches = 1;
return (dwError);
error:
if (pTxFilters) {
FreeTxFilters(
dwNumFilters,
pTxFilters
);
}
if (pQMPolicies) {
FreeQMPolicies(
dwNumPolicies,
pQMPolicies
);
}
*ppTxFilters = NULL;
*ppQMPolicies = NULL;
*pdwNumMatches = 0;
return (dwError);
}
DWORD
CopyDefaultTxFilter(
PTRANSPORT_FILTER pTxFilter,
PINIQMPOLICY pIniQMPolicy
)
{
DWORD dwError = 0;
UuidCreate(&(pTxFilter->gFilterID));
dwError = CopyName(
L"0",
&(pTxFilter->pszFilterName)
);
BAIL_ON_WIN32_ERROR(dwError);
pTxFilter->InterfaceType = INTERFACE_TYPE_ALL;
pTxFilter->bCreateMirror = TRUE;
pTxFilter->dwFlags = 0;
pTxFilter->dwFlags |= IPSEC_QM_POLICY_DEFAULT_POLICY;
pTxFilter->SrcAddr.AddrType = IP_ADDR_SUBNET;
pTxFilter->SrcAddr.uIpAddr = SUBNET_ADDRESS_ANY;
pTxFilter->SrcAddr.uSubNetMask = SUBNET_MASK_ANY;
pTxFilter->DesAddr.AddrType = IP_ADDR_SUBNET;
pTxFilter->DesAddr.uIpAddr = SUBNET_ADDRESS_ANY;
pTxFilter->DesAddr.uSubNetMask = SUBNET_MASK_ANY;
pTxFilter->Protocol.ProtocolType = PROTOCOL_UNIQUE;
pTxFilter->Protocol.dwProtocol = 0;
pTxFilter->SrcPort.PortType = PORT_UNIQUE;
pTxFilter->SrcPort.wPort = 0;
pTxFilter->DesPort.PortType = PORT_UNIQUE;
pTxFilter->DesPort.wPort = 0;
pTxFilter->InboundFilterFlag = NEGOTIATE_SECURITY;
pTxFilter->OutboundFilterFlag = NEGOTIATE_SECURITY;
pTxFilter->dwDirection = 0;
pTxFilter->dwWeight = 0;
CopyGuid(pIniQMPolicy->gPolicyID, &(pTxFilter->gPolicyID));
error:
return (dwError);
}
DWORD
SeparateInterfaceAddresses(
PADDR pAddrList,
DWORD dwAddrCnt,
MATCHING_ADDR * pMatchingAddresses,
DWORD dwLocalAddrCnt,
PADDR * ppIsMeAddrList,
PDWORD pdwIsMeAddrCnt,
PADDR * ppIsNotMeAddrList,
PDWORD pdwIsNotMeAddrCnt
)
{
DWORD dwError = 0;
PADDR pIsMeAddrList = NULL;
DWORD i = 0;
if (dwAddrCnt) {
dwError = AllocateSPDMemory(
sizeof(ADDR) * dwAddrCnt,
&pIsMeAddrList
);
BAIL_ON_WIN32_ERROR(dwError);
}
for (i = 0; i < dwAddrCnt; i++) {
memcpy(
&(pIsMeAddrList[i]),
&(pAddrList[i]),
sizeof(ADDR)
);
}
*ppIsMeAddrList = pIsMeAddrList;
*pdwIsMeAddrCnt = dwAddrCnt;
*ppIsNotMeAddrList = NULL;
*pdwIsNotMeAddrCnt = 0;
return (dwError);
error:
if (pIsMeAddrList) {
FreeSPDMemory(pIsMeAddrList);
}
*ppIsMeAddrList = NULL;
*pdwIsMeAddrCnt = 0;
*ppIsNotMeAddrList = NULL;
*pdwIsNotMeAddrCnt = 0;
return (dwError);
}