Leaked source code of windows server 2003
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.
 
 
 
 
 
 

398 lines
9.6 KiB

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
encap-hw.c
Abstract:
This module contains all the IPSec routines for UDP ESP encapsulation
SA and parsing entry offload.
Author:
AbhisheV
Environment:
Kernel Level
Revision History:
--*/
#include "precomp.h"
VOID
IPSecFillHwAddEncapSa(
PSA_TABLE_ENTRY pSwSa,
PPARSER_IFENTRY pParserIfEntry,
PUCHAR pucBuffer,
ULONG uBufLen
)
/*++
Routine Description:
Fills in the hardware add encapsulation sa buffer from the passed in
software encapsulation sa.
Arguments:
pSwSa - Pointer to the software encapsulation sa structure.
pParserIfEntry - Pointer to the parser interface entry.
pucBuffer - Pointer to the hardware add encapsulation sa buffer.
uBufLen - Length of the buffer.
Return Value:
None - VOID.
--*/
{
POFFLOAD_IPSEC_ADD_UDPESP_SA pHwSa = (POFFLOAD_IPSEC_ADD_UDPESP_SA) pucBuffer;
POFFLOAD_SECURITY_ASSOCIATION pHwSaInfo = NULL;
LONG lIndex = 0;
ULONG uOffset = 0;
pHwSa->SrcAddr = pSwSa->SA_SRC_ADDR;
pHwSa->SrcMask = pSwSa->SA_SRC_MASK;
pHwSa->DstAddr = pSwSa->SA_DEST_ADDR;
pHwSa->DstMask = pSwSa->SA_DEST_MASK;
pHwSa->Protocol = pSwSa->SA_PROTO;
pHwSa->SrcPort = SA_SRC_PORT(pSwSa);
pHwSa->DstPort = SA_DEST_PORT(pSwSa);
pHwSa->SrcTunnelAddr = 0;
pHwSa->DstTunnelAddr = 0;
if (pSwSa->sa_Flags & FLAGS_SA_TUNNEL) {
pHwSa->SrcTunnelAddr = pSwSa->sa_SrcTunnelAddr;
pHwSa->DstTunnelAddr = pSwSa->sa_TunnelAddr;
}
pHwSa->Flags = 0;
if (pSwSa->sa_Flags & FLAGS_SA_OUTBOUND) {
pHwSa->Flags |= OFFLOAD_OUTBOUND_SA;
}
else {
pHwSa->Flags |= OFFLOAD_INBOUND_SA;
}
pHwSa->NumSAs = (SHORT) pSwSa->sa_NumOps;
ASSERT(OFFLOAD_MAX_SAS >= pSwSa->sa_NumOps);
pHwSa->KeyLen = 0;
for (lIndex = 0; lIndex < pSwSa->sa_NumOps; lIndex++) {
pHwSaInfo = &pHwSa->SecAssoc[lIndex];
pHwSaInfo->Operation = pSwSa->sa_Operation[lIndex];
pHwSaInfo->SPI = pSwSa->sa_OtherSPIs[lIndex];
pHwSaInfo->EXT_INT_ALGO = pSwSa->INT_ALGO(lIndex);
pHwSaInfo->EXT_INT_KEYLEN = pSwSa->INT_KEYLEN(lIndex);
pHwSaInfo->EXT_INT_ROUNDS = pSwSa->INT_ROUNDS(lIndex);
pHwSaInfo->EXT_CONF_ALGO = pSwSa->CONF_ALGO(lIndex);
pHwSaInfo->EXT_CONF_KEYLEN = pSwSa->CONF_KEYLEN(lIndex);
pHwSaInfo->EXT_CONF_ROUNDS = pSwSa->CONF_ROUNDS(lIndex);
ASSERT(
(uBufLen >= (sizeof(OFFLOAD_IPSEC_ADD_UDPESP_SA) +
pHwSa->KeyLen +
pSwSa->INT_KEYLEN(lIndex) +
pSwSa->CONF_KEYLEN(lIndex)))
);
RtlCopyMemory(
pHwSa->KeyMat + uOffset,
pSwSa->CONF_KEY(lIndex),
pSwSa->CONF_KEYLEN(lIndex)
);
RtlCopyMemory(
pHwSa->KeyMat + uOffset + pSwSa->CONF_KEYLEN(lIndex),
pSwSa->INT_KEY(lIndex),
pSwSa->INT_KEYLEN(lIndex)
);
uOffset += pSwSa->INT_KEYLEN(lIndex) + pSwSa->CONF_KEYLEN(lIndex);
pHwSa->KeyLen += uOffset;
}
pHwSa->OffloadHandle = NULL;
if (NULL != pParserIfEntry) {
ASSERT (!(pSwSa->sa_Flags & FLAGS_SA_OUTBOUND));
pHwSa->EncapTypeEntry.UdpEncapType = pParserIfEntry->UdpEncapType;
pHwSa->EncapTypeEntry.DstEncapPort = pParserIfEntry->usDstEncapPort;
pHwSa->EncapTypeEntryOffldHandle = pParserIfEntry->hParserIfOffload;
} else {
ASSERT (pSwSa->sa_Flags & FLAGS_SA_OUTBOUND);
if (SA_UDP_ENCAP_TYPE_IKE == pSwSa->sa_EncapType) {
pHwSa->EncapTypeEntry.UdpEncapType = OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_IKE;
} else if (SA_UDP_ENCAP_TYPE_OTHER == pSwSa->sa_EncapType) {
pHwSa->EncapTypeEntry.UdpEncapType = OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_OTHER;
} else {
ASSERT (0);
}
pHwSa->EncapTypeEntry.DstEncapPort = pSwSa->sa_EncapContext.wSrcEncapPort;
pHwSa->EncapTypeEntryOffldHandle = NULL;
}
return;
}
PPARSER_IFENTRY
FindParserIfEntry (
PPARSER_IFENTRY pParserIfEntry,
PSA_TABLE_ENTRY pSa,
Interface * pInterface
)
{
ASSERT (!(pSa->sa_Flags & FLAGS_SA_OUTBOUND));
while (NULL != pParserIfEntry) {
if ( SA_UDP_ENCAP_TYPE_IKE == pSa->sa_EncapType ) {
if (pParserIfEntry->UdpEncapType == OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_IKE &&
pParserIfEntry->usDstEncapPort == pSa->sa_EncapContext.wDesEncapPort &&
pParserIfEntry->hInterface == pInterface) {
break;
}
} else if (SA_UDP_ENCAP_TYPE_OTHER == pSa->sa_EncapType ) {
if (pParserIfEntry->UdpEncapType == OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_OTHER &&
pParserIfEntry->usDstEncapPort == pSa->sa_EncapContext.wDesEncapPort &&
pParserIfEntry->hInterface == pInterface) {
break;
}
} else {
ASSERT (0);
}
pParserIfEntry = pParserIfEntry->pNext;
}
return pParserIfEntry;
}
NTSTATUS
CreateParserIfEntry(
PSA_TABLE_ENTRY pSa,
Interface * pInterface,
PPARSER_IFENTRY * ppParserIfEntry
)
{
PPARSER_IFENTRY pParserIfEntry = NULL;
NTSTATUS ntStatus = STATUS_SUCCESS;
pParserIfEntry = IPSecAllocateMemory(sizeof(PARSER_IFENTRY), IPSEC_TAG_PARSER);
if (NULL == pParserIfEntry) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
BAIL_ON_NTSTATUS_ERROR(ntStatus);
}
RtlZeroMemory (pParserIfEntry, sizeof(PARSER_IFENTRY));
ASSERT (!(pSa->sa_Flags & FLAGS_SA_OUTBOUND));
if (SA_UDP_ENCAP_TYPE_IKE == pSa->sa_EncapType ) {
pParserIfEntry->UdpEncapType = OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_IKE;
} else if (SA_UDP_ENCAP_TYPE_OTHER == pSa->sa_EncapType ) {
pParserIfEntry->UdpEncapType = OFFLOAD_IPSEC_UDPESP_ENCAPTYPE_OTHER;
} else {
ASSERT (0);
}
pParserIfEntry->usDstEncapPort = pSa->sa_EncapContext.wDesEncapPort;
pParserIfEntry->hInterface = pInterface;
pParserIfEntry->hParserIfOffload = NULL;
pParserIfEntry->uRefCnt = 1;
*ppParserIfEntry = pParserIfEntry;
return ntStatus;
error:
*ppParserIfEntry = NULL;
return ntStatus;
}
NTSTATUS
GetParserEntry(
PSA_TABLE_ENTRY pSa,
Interface * pInterface,
PPARSER_IFENTRY * ppParserIfEntry
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PPARSER_IFENTRY pParserIfEntry = NULL;
pParserIfEntry = FindParserIfEntry(
gpParserIfEntry,
pSa,
pInterface
);
if (NULL == pParserIfEntry) {
ntStatus = CreateParserIfEntry(pSa, pInterface, &pParserIfEntry);
BAIL_ON_NTSTATUS_ERROR(ntStatus);
pParserIfEntry->pNext = gpParserIfEntry;
gpParserIfEntry = pParserIfEntry;
}
IPSEC_INCREMENT(pParserIfEntry->uRefCnt);
*ppParserIfEntry = pParserIfEntry;
return (ntStatus);
error:
*ppParserIfEntry = NULL;
return (ntStatus);
}
VOID
RemoveParserEntry (
PPARSER_IFENTRY pParserIfEntry
)
{
PPARSER_IFENTRY * ppTemp = NULL;
ppTemp = &gpParserIfEntry;
while (*ppTemp) {
if (*ppTemp == pParserIfEntry) {
break;
}
ppTemp = &((*ppTemp)->pNext);
}
if (*ppTemp) {
*ppTemp = pParserIfEntry->pNext;
} else {
ASSERT (0);
}
return;
}
VOID
DerefParserEntry(
PPARSER_IFENTRY pParserIfEntry
)
{
if (1 == IPSEC_DECREMENT(pParserIfEntry->uRefCnt)) {
RemoveParserEntry (pParserIfEntry);
IPSecFreeMemory (pParserIfEntry);
}
}
HANDLE
UploadParserEntryAndGetHandle(
PSA_TABLE_ENTRY pSa,
Interface * pInterface
)
{
PPARSER_IFENTRY pParserIfEntry = NULL;
HANDLE hOffloadHandle = NULL;
pParserIfEntry = FindParserIfEntry(
gpParserIfEntry,
pSa,
pInterface
);
if (NULL != pParserIfEntry) {
if (IPSEC_GET_VALUE(pParserIfEntry->uRefCnt) == 2) {
hOffloadHandle = pParserIfEntry->hParserIfOffload;
}
DerefParserEntry (pParserIfEntry);
}
return hOffloadHandle;
}
VOID
FlushParserEntriesForInterface(
Interface * pInterface
)
{
PPARSER_IFENTRY pParserIfEntry = gpParserIfEntry;
PPARSER_IFENTRY pPrevParserIfEntry = NULL;
PPARSER_IFENTRY pTemp = NULL;
while (NULL != pParserIfEntry) {
if (pParserIfEntry->hInterface == pInterface) {
pTemp = pParserIfEntry;
pParserIfEntry = pParserIfEntry->pNext;
if (NULL != pPrevParserIfEntry) {
pPrevParserIfEntry->pNext = pParserIfEntry;
} else {
gpParserIfEntry = pParserIfEntry;
}
IPSecFreeMemory (pTemp);
} else {
pPrevParserIfEntry = pParserIfEntry;
pParserIfEntry = pParserIfEntry->pNext;
}
}
return;
}
VOID
FlushAllParserEntries(
)
{
PPARSER_IFENTRY pParserIfEntry = gpParserIfEntry;
PPARSER_IFENTRY pTemp = NULL;
while (NULL != pParserIfEntry) {
pTemp = pParserIfEntry;
pParserIfEntry = pParserIfEntry->pNext;
IPSecFreeMemory (pTemp);
}
gpParserIfEntry = NULL;
return;
}