|
|
/*++
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, PSPECIAL_ADDR pSpecialAddrsList, 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_V4 pOutSrcAddrList = NULL; DWORD dwOutSrcAddrCnt = 0; PADDR_V4 pInSrcAddrList = NULL; DWORD dwInSrcAddrCnt = 0;
PADDR_V4 pOutDesAddrList = NULL; DWORD dwOutDesAddrCnt = 0; PADDR_V4 pInDesAddrList = NULL; DWORD dwInDesAddrCnt = 0;
//
// Form the outbound and inbound source and destination
// address lists.
//
dwError = FormTxOutboundInboundAddresses( pFilter, pMatchingAddresses, dwAddrCnt, pSpecialAddrsList, &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, PSPECIAL_ADDR pSpecialAddrsList, PADDR_V4 * ppOutSrcAddrList, PDWORD pdwOutSrcAddrCnt, PADDR_V4 * ppInSrcAddrList, PDWORD pdwInSrcAddrCnt, PADDR_V4 * ppOutDesAddrList, PDWORD pdwOutDesAddrCnt, PADDR_V4 * 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_V4 pSrcAddrList = NULL; DWORD dwSrcAddrCnt = 0; PADDR_V4 pDesAddrList = NULL; DWORD dwDesAddrCnt = 0;
PADDR_V4 pOutSrcAddrList = NULL; DWORD dwOutSrcAddrCnt = 0; PADDR_V4 pInSrcAddrList = NULL; DWORD dwInSrcAddrCnt = 0;
PADDR_V4 pOutDesAddrList = NULL; DWORD dwOutDesAddrCnt = 0; PADDR_V4 pInDesAddrList = NULL; DWORD dwInDesAddrCnt = 0;
//
// Replace wild card information to generate the new source
// address list.
//
dwError = FormAddressList( pFilter->SrcAddr, pMatchingAddresses, dwAddrCnt, pSpecialAddrsList, pFilter->InterfaceType, &pSrcAddrList, &dwSrcAddrCnt ); BAIL_ON_WIN32_ERROR(dwError);
//
// Replace wild card information to generate the new destination
// address list.
//
dwError = FormAddressList( pFilter->DesAddr, pMatchingAddresses, dwAddrCnt, pSpecialAddrsList, pFilter->InterfaceType, &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_V4 InAddr, MATCHING_ADDR * pMatchingAddresses, DWORD dwAddrCnt, PSPECIAL_ADDR pSpecialAddrsList, IF_TYPE FilterInterfaceType, PADDR_V4 * 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_V4 pOutAddr = NULL; DWORD dwOutAddrCnt = 0; PSPECIAL_ADDR pSpecialAddr; DWORD i = 0, j = 0; BOOL bMatches = FALSE;
switch(InAddr.AddrType) {
case IP_ADDR_UNIQUE:
if (InAddr.uIpAddr == IP_ADDRESS_ME) {
dwError = AllocateSPDMemory( sizeof(ADDR_V4) * 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_V4), &pOutAddr ); BAIL_ON_WIN32_ERROR(dwError);
memcpy(pOutAddr, &InAddr, sizeof(ADDR_V4)); dwOutAddrCnt = 1;
}
break;
case IP_ADDR_SUBNET:
dwError = AllocateSPDMemory( sizeof(ADDR_V4), &pOutAddr ); BAIL_ON_WIN32_ERROR(dwError);
memcpy(pOutAddr, &InAddr, sizeof(ADDR_V4)); 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_V4) * 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; default: if (IsSpecialServ(InAddr.AddrType)) { for (pSpecialAddr = pSpecialAddrsList; pSpecialAddr; pSpecialAddr = pSpecialAddr->pNext) { //
// Match only if interface types match, or in case of
// INTERFACE_TYPE_ALL match only first occurence
//
if ((FilterInterfaceType == pSpecialAddr->InterfaceType) || (FilterInterfaceType == INTERFACE_TYPE_ALL && !pSpecialAddr->bDupInterface)) {
if (InAddr.AddrType == pSpecialAddr->AddrType) { dwOutAddrCnt++; } } } if (dwOutAddrCnt) { dwError = AllocateSPDMemory( sizeof(ADDR_V4) * dwOutAddrCnt, &pOutAddr ); BAIL_ON_WIN32_ERROR(dwError);
for (pSpecialAddr = pSpecialAddrsList; pSpecialAddr; pSpecialAddr = pSpecialAddr->pNext) { if ((FilterInterfaceType == pSpecialAddr->InterfaceType) || (FilterInterfaceType == INTERFACE_TYPE_ALL && !pSpecialAddr->bDupInterface)) {
if (InAddr.AddrType == pSpecialAddr->AddrType) { pOutAddr[j].AddrType = IP_ADDR_UNIQUE; pOutAddr[j].uIpAddr = pSpecialAddr->uIpAddr; pOutAddr[j].uSubNetMask = IP_ADDRESS_MASK_NONE; 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_V4 pAddrList, DWORD dwAddrCnt, MATCHING_ADDR * pMatchingAddresses, DWORD dwLocalAddrCnt, PADDR_V4 * ppOutAddrList, PDWORD pdwOutAddrCnt, PADDR_V4 * 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;
default: if (IsSpecialServ(AddrType)) { dwError = SeparateUniqueAddresses( pAddrList, dwAddrCnt, pMatchingAddresses, dwLocalAddrCnt, ppOutAddrList, pdwOutAddrCnt, ppInAddrList, pdwInAddrCnt ); BAIL_ON_WIN32_ERROR(dwError); } break; }
error:
return (dwError); }
DWORD FormSpecificTxFilters( PINITXFILTER pFilter, PADDR_V4 pSrcAddrList, DWORD dwSrcAddrCnt, PADDR_V4 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_V4 pAddrList, DWORD dwAddrCnt, MATCHING_ADDR * pMatchingAddresses, DWORD dwLocalAddrCnt, PADDR_V4 * ppIsMeAddrList, PDWORD pdwIsMeAddrCnt, PADDR_V4 * 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_V4 pIsMeAddrList = NULL; DWORD dwIsMeAddrCnt = 0; PADDR_V4 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_V4) * dwIsMeAddrCnt, &pIsMeAddrList ); BAIL_ON_WIN32_ERROR(dwError); }
if (dwIsNotMeAddrCnt) { dwError = AllocateSPDMemory( sizeof(ADDR_V4) * 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_V4) ); j++;
memcpy( &pIsNotMeAddrList[k], &pAddrList[i], sizeof(ADDR_V4) ); k++;
break;
case FALSE:
bEqual = InterfaceAddrIsLocal( pAddrList[i].uIpAddr, pAddrList[i].uSubNetMask, pMatchingAddresses, dwLocalAddrCnt ); if (bEqual) { memcpy( &(pIsMeAddrList[j]), &(pAddrList[i]), sizeof(ADDR_V4) ); j++; } else { bEqual = IsMyAddress( pAddrList[i].uIpAddr, pAddrList[i].uSubNetMask, gpInterfaceList ); if (!bEqual) { memcpy( &pIsNotMeAddrList[k], &pAddrList[i], sizeof(ADDR_V4) ); 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_V4 pAddrList, DWORD dwAddrCnt, MATCHING_ADDR * pMatchingAddresses, DWORD dwLocalAddrCnt, PADDR_V4 * ppIsMeAddrList, PDWORD pdwIsMeAddrCnt, PADDR_V4 * 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_V4 pIsMeAddrList = NULL; DWORD dwIsMeAddrCnt = 0; PADDR_V4 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_V4) * dwIsMeAddrCnt, &pIsMeAddrList ); BAIL_ON_WIN32_ERROR(dwError); }
if (dwIsNotMeAddrCnt) { dwError = AllocateSPDMemory( sizeof(ADDR_V4) * 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_V4) ); j++; break;
case FALSE:
bEqual = InterfaceAddrIsLocal( pAddrList[i].uIpAddr, pAddrList[i].uSubNetMask, pMatchingAddresses, dwLocalAddrCnt ); if (bEqual) { memcpy( &(pIsMeAddrList[j]), &(pAddrList[i]), sizeof(ADDR_V4) ); j++; } break;
}
memcpy( &pIsNotMeAddrList[k], &pAddrList[i], sizeof(ADDR_V4) ); 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_V4 SrcAddr, ADDR_V4 DesAddr, PINITXSFILTER * ppSpecificFilter ) { DWORD dwError = 0; PINITXSFILTER pSpecificFilter = NULL;
dwError = AllocateSPDMemory( sizeof(INITXSFILTER), &pSpecificFilter ); BAIL_ON_WIN32_ERROR(dwError);
pSpecificFilter->cRef = 0;
pSpecificFilter->IpVersion = pGenericFilter->IpVersion;
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->InboundFilterAction = pGenericFilter->InboundFilterAction;
pSpecificFilter->OutboundFilterAction = pGenericFilter->OutboundFilterAction;
//
// 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 dwSrcMaskWeight = 0; DWORD dwDesMaskWeight = 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); dwDesMaskWeight += (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); dwSrcMaskWeight += (i+1); }
//
// Move to the next bit position.
//
SrcMask = SrcMask >> 1;
}
if (dwDesMaskWeight >= dwSrcMaskWeight) { dwWeight |= WEIGHT_ADDRESS_TIE_BREAKER; }
//
// 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 (pListMerge) { 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;
pTxFilter->IpVersion = pIniTxSFilter->IpVersion;
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;
dwError = CopyIntToExtAddresses(pIniTxSFilter->SrcAddr, &(pTxFilter->SrcAddr)); BAIL_ON_WIN32_ERROR(dwError);
dwError = CopyIntToExtAddresses(pIniTxSFilter->DesAddr, &(pTxFilter->DesAddr)); BAIL_ON_WIN32_ERROR(dwError);
CopyProtocols(pIniTxSFilter->Protocol, &(pTxFilter->Protocol));
CopyPorts(pIniTxSFilter->SrcPort, &(pTxFilter->SrcPort));
CopyPorts(pIniTxSFilter->DesPort, &(pTxFilter->DesPort));
pTxFilter->InboundFilterAction = pIniTxSFilter->InboundFilterAction;
pTxFilter->OutboundFilterAction = pIniTxSFilter->OutboundFilterAction;
pTxFilter->dwDirection = pIniTxSFilter->dwDirection;
pTxFilter->dwWeight = pIniTxSFilter->dwWeight;
CopyGuid(pIniTxSFilter->gPolicyID, &(pTxFilter->gPolicyID));
return (dwError);
error:
if (pTxFilter->pszFilterName) { SPDApiBufferFree(pTxFilter->pszFilterName); pTxFilter->pszFilterName = NULL; }
if (pTxFilter->SrcAddr.pgInterfaceID) { SPDApiBufferFree(pTxFilter->SrcAddr.pgInterfaceID); pTxFilter->SrcAddr.pgInterfaceID = NULL; }
if (pTxFilter->DesAddr.pgInterfaceID) { SPDApiBufferFree(pTxFilter->DesAddr.pgInterfaceID); pTxFilter->DesAddr.pgInterfaceID = NULL; }
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, DWORD dwVersion, PTRANSPORT_FILTER pTxFilter, DWORD dwFlags, DWORD dwPreferredNumEntries, PTRANSPORT_FILTER * ppMatchedTxFilters, PIPSEC_QM_POLICY * ppMatchedQMPolicies, LPDWORD pdwNumMatches, LPDWORD pdwResumeHandle, LPVOID pvReserved ) /*++
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( dwFlags, &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( dwFlags, &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( dwFlags, 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( dwFlags, 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->InboundFilterAction != NEGOTIATE_SECURITY) && (pIniTxSFilter->OutboundFilterAction != 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( DWORD dwFlags, 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( dwFlags, 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; RPC_STATUS RpcStatus = RPC_S_OK;
pTxFilter->IpVersion = IPSEC_PROTOCOL_V4;
RpcStatus = UuidCreate(&(pTxFilter->gFilterID)); if (!(RpcStatus == RPC_S_OK || RpcStatus == RPC_S_UUID_LOCAL_ONLY)) { dwError = RPC_S_CALL_FAILED; BAIL_ON_WIN32_ERROR(dwError); }
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->SrcAddr.pgInterfaceID = NULL;
pTxFilter->DesAddr.AddrType = IP_ADDR_SUBNET; pTxFilter->DesAddr.uIpAddr = SUBNET_ADDRESS_ANY; pTxFilter->DesAddr.uSubNetMask = SUBNET_MASK_ANY; pTxFilter->DesAddr.pgInterfaceID = NULL;
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->InboundFilterAction = NEGOTIATE_SECURITY;
pTxFilter->OutboundFilterAction = NEGOTIATE_SECURITY;
pTxFilter->dwDirection = 0;
pTxFilter->dwWeight = 0;
CopyGuid(pIniQMPolicy->gPolicyID, &(pTxFilter->gPolicyID));
error:
return (dwError); }
DWORD SeparateInterfaceAddresses( PADDR_V4 pAddrList, DWORD dwAddrCnt, MATCHING_ADDR * pMatchingAddresses, DWORD dwLocalAddrCnt, PADDR_V4 * ppIsMeAddrList, PDWORD pdwIsMeAddrCnt, PADDR_V4 * ppIsNotMeAddrList, PDWORD pdwIsNotMeAddrCnt ) { DWORD dwError = 0; PADDR_V4 pIsMeAddrList = NULL; DWORD i = 0;
if (dwAddrCnt) { dwError = AllocateSPDMemory( sizeof(ADDR_V4) * dwAddrCnt, &pIsMeAddrList ); BAIL_ON_WIN32_ERROR(dwError); }
for (i = 0; i < dwAddrCnt; i++) {
memcpy( &(pIsMeAddrList[i]), &(pAddrList[i]), sizeof(ADDR_V4) );
}
*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); }
|