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.
|
|
/*++
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; }
|