vpnengine/ikev2lib/src/ikev2sa.cpp
changeset 0 33413c0669b9
child 10 68dc8923de26
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev2lib/src/ikev2sa.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,293 @@
+/*
+* Copyright (c) 2003-2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  IKEv2 SA
+*
+*/
+
+
+#include "ikedebug.h"
+#include "ikev2SA.h"
+#include "ikepolparser.h"
+#include "ikev2ipsecsadata.h"
+#include "ikev2pluginsession.h"
+
+CIkev2SA* CIkev2SA::NewL(CIkev2PluginSession& aIkeV2PluginSession, TIkev2SAData& aIkev2SAdata, MIkeDebug& aDebug)
+{
+	CIkev2SA *sa = new (ELeave) CIkev2SA(aIkeV2PluginSession, aDebug);
+	sa->ConstructL(aIkev2SAdata);
+	return sa;
+}
+
+
+CIkev2SA::CIkev2SA(CIkev2PluginSession& aIkeV2PluginSession, MIkeDebug& aDebug)
+:CTimer(EPriorityStandard), iIkeV2PluginSession(aIkeV2PluginSession), iDebug(aDebug)
+{
+    CActiveScheduler::Add(this);
+}
+
+
+void CIkev2SA::ConstructL(TIkev2SAData& aIkev2SAdata)
+{
+	CTimer::ConstructL();		
+	iIkeV2SaData.Copy(aIkev2SAdata);
+	//
+	// Calculate lifetime value for the new IKE SA
+	// The jitter value is adjusted from SA internal ID (SAId mod 8) 
+	//
+    iRemainingTime = iIkeV2SaData.iLifetime + (iIkeV2SaData.SaId() % 8);
+	iIkeV2SaData.iSAState  = KSaStateReady;
+
+	TInt DPDHeartbeat = 0;
+	if ( iIkeV2SaData.iIkeData->iDPDHeartBeat )
+	   DPDHeartbeat = iIkeV2SaData.iIkeData->iDPDHeartBeat;      
+
+	if ( DPDHeartbeat )
+	{
+		iIkeKeepAlive = CIkeV2KeepAlive::NewL(DPDHeartbeat, *this);
+	}
+										  
+	DEBUG_LOG2(_L("IKEv2 SA constructed, SAId: %d, Lifetime: %d"), iIkeV2SaData.SaId(), iRemainingTime);
+	
+	StartTimer();
+}
+
+
+CIkev2SA::~CIkev2SA()
+{
+    if (IsActive())
+        Cancel();
+	PurgeIpsecDataQue();  	
+	iIkeV2SaData.CleanUp();
+	delete iIkeKeepAlive;	
+}
+
+
+void CIkev2SA::DoCancel()
+{
+    CTimer::DoCancel();
+}
+
+void CIkev2SA::UpdateL(TIkev2SAData* aIkev2SAdata, TIkeV2IpsecSAData* aIpsecSAdata)
+{
+    DEBUG_LOG(_L("CIkev2SA::UpdateL"));
+
+	if ( aIkev2SAdata )
+	{
+	   //
+	   // Update IKE Sa data information and reset/restart IKE SA lifetime
+	   //
+	    iIkeV2SaData.Copy(*aIkev2SAdata);
+	    iIkeV2SaData.iSAState = KSaStateReady;		
+	}
+	if ( aIpsecSAdata )
+	{
+	   //
+	   // Link an Ipsec SA pair information into IKE SA
+	   //
+		TIkeV2IpsecSAData* IpsecSA = new (ELeave) TIkeV2IpsecSAData(iDebug);
+		IpsecSA->Copy(*aIpsecSAdata);
+		LinkIpsecSa(IpsecSA);						  
+		DEBUG_LOG3(_L("Ipsec SA added into IKE SA, SAId: %d, In SPI: %d, Out SPI: %d"),
+				   iIkeV2SaData.SaId(), &aIpsecSAdata->iSPI_In, &aIpsecSAdata->iSPI_Out);
+	}
+}
+
+TBool CIkev2SA::RemoteAddrChanged(TInetAddr& aNewIp)
+{
+
+#if __DEBUG
+	TBuf<40> txt_addr;				
+	aNewIp.OutputWithScope(txt_addr);
+	DEBUG_LOG2(_L("Remote IP changed IKE SA: %d, new address %S"), iIkeV2SaData.SaId(), &txt_addr);
+#endif //__DEBUG
+	aNewIp = aNewIp; //To silence UREL warnings: contents of DEB macro invisible in UREL builds
+	
+	return ETrue;
+}
+
+
+TIkeV2IpsecSAData* CIkev2SA::RemoveIpsecSaData(const TDesC8& aInSpi, const TDesC8& aOutSpi)
+{ 
+    return FindIpsecSaData(aInSpi, aOutSpi, ETrue); 
+} 
+
+
+TIkeV2IpsecSAData* CIkev2SA::FindIpsecSaData(const TDesC8& aInSpi, const TDesC8& aOutSpi, TBool aRemove)
+{
+
+    __ASSERT_DEBUG( aInSpi.Length() == 4 || aInSpi.Length() == 0, User::Invariant() );
+    __ASSERT_DEBUG( aOutSpi.Length() == 4 || aOutSpi.Length() == 0, User::Invariant() );
+    __ASSERT_DEBUG( aInSpi.Length() != 0 || aOutSpi.Length() != 0, User::Invariant() );
+
+	TInt Found = 0;
+	if ( aInSpi.Length() > 0 )
+		Found ++;
+	if ( aOutSpi.Length() > 0 )
+		Found ++;
+	if ( Found == 0 )
+	   return NULL;	
+
+	TInt Match;
+	TIkeV2IpsecSAData* Prev = NULL;
+	TIkeV2IpsecSAData* Sa   = iIpsecSaQue;
+
+	while ( Sa )
+	{
+		Match = 0;
+		if ( aInSpi.Length() > 0 && (aInSpi.Compare(Sa->iSPI_In) == 0))
+           Match ++;   		
+		if ( aOutSpi.Length() > 0 && (aOutSpi.Compare(Sa->iSPI_Out) == 0) )
+		   Match ++;
+		if ( Match == Found )
+		{
+		   if ( aRemove )
+		   {
+			  if ( Prev )
+				   Prev->iNext = Sa->iNext;
+			  else iIpsecSaQue = Sa->iNext;
+		   }	   
+		   break;
+		}
+		Prev = Sa;
+		Sa   = Sa->iNext;
+	}
+	return Sa;
+}
+
+void CIkev2SA::DeleteIpsecSaData(const TDesC8& aInSpi, const TDesC8& aOutSpi)
+{
+	TIkeV2IpsecSAData* SaData = FindIpsecSaData(aInSpi, aOutSpi, ETrue);
+	if ( SaData )
+	{
+		SaData->PurgeKeyMaterial();
+		SaData->DeleteRekeyData();
+		DeleteIpsecSas(SaData);		
+		delete SaData;
+	}	
+}
+
+void CIkev2SA::LinkIpsecSa(TIkeV2IpsecSAData* aSa) 
+{
+    ASSERT(aSa);
+    aSa->iNext = iIpsecSaQue; 
+    iIpsecSaQue = aSa;
+}   
+
+void CIkev2SA::PurgeIpsecDataQue()
+{
+	
+	TIkeV2IpsecSAData* Sa = iIpsecSaQue;
+	while ( iIpsecSaQue )
+	{
+		iIpsecSaQue = Sa->iNext;
+		Sa->PurgeKeyMaterial();
+		Sa->DeleteRekeyData();
+		DeleteIpsecSas(Sa);
+		delete Sa;
+		Sa = iIpsecSaQue;
+	}	
+}
+
+void CIkev2SA::DeleteIpsecSas(TIkeV2IpsecSAData* aSa)
+{
+    ASSERT(aSa);
+	TInetAddr LocalAddr;
+	if ( aSa->iSrcSpecific )
+		 LocalAddr = iIkeV2SaData.iLocalAddr;
+	else LocalAddr.Init(0); 
+	LocalAddr.SetPort(0);	
+	TInetAddr RemoteAddr = iIkeV2SaData.iRemoteAddr;
+	RemoteAddr.SetPort(0);
+	if ( aSa->iSPI_In.Length() > 0 ) 
+	{
+        TUint32 spi;
+        TPtr8 spiPtr(reinterpret_cast<TUint8*>(&spi), sizeof(spi));
+        spiPtr = aSa->iSPI_In;
+		iIkeV2PluginSession.DeleteIpsecSA(spi, RemoteAddr, LocalAddr, aSa->iSaType);
+	}
+	if ( aSa->iSPI_Out.Length() > 0 )
+	{
+        TUint32 spi;
+        TPtr8 spiPtr(reinterpret_cast<TUint8*>(&spi), sizeof(spi));
+        spiPtr = aSa->iSPI_Out;
+        iIkeV2PluginSession.DeleteIpsecSA(spi, LocalAddr, RemoteAddr, aSa->iSaType);
+	}
+}
+
+
+void CIkev2SA::RunL()
+{
+	//
+	// If IKE SA lifetime expired, delete IKE SA if there is no
+	// active IPSEC SA:s alive. If there is rekey IKE SA.
+	//
+    DEBUG_LOG2(_L("CIkev2SA::RunL, SAId=%d, remaining time=%d"),
+            iIkeV2SaData.SaId(), iRemainingTime );
+	if (iRemainingTime == 0) 
+	{										 		
+		if ( iIpsecSaQue )
+		{
+		    iIkeV2PluginSession.RekeyIkeSAL(&iIkeV2SaData);
+		}
+		else 
+		{		 
+		    iIkeV2PluginSession.DeleteIkeSAL(&iIkeV2SaData, ETrue); // "Normal" close
+		}
+	}
+	else StartTimer();
+	
+}
+
+void CIkev2SA::StartTimer()
+{
+	if (iRemainingTime > KMaxTInt/SECOND)   //To avoid overflowing the Timer
+	{
+		iRemainingTime -= KMaxTInt/SECOND;
+		After(KMaxTInt);
+	}
+	else    //No overflow
+	{
+		After(iRemainingTime*SECOND);
+		iRemainingTime = 0;
+	}
+}
+
+
+void CIkev2SA::EventHandlerL()
+{
+	//
+	// The implementation for class MDpdHeartBeatEventHandler virtual function
+	// This method is called by an CIkeKeepAlive object instance when
+	// DPD heartbeat timeout has elapsed.
+	//
+    iIkeV2PluginSession.KeepAliveIkeSAL(&iIkeV2SaData);
+}
+
+
+TIkeV2IpsecSAData* CIkev2SA::GetIpsecSaQue()
+{ 
+    TIkeV2IpsecSAData* Que = iIpsecSaQue; 
+    iIpsecSaQue = NULL; 
+    return Que; 
+}
+
+
+void CIkev2SA::SetIpsecSaQue(TIkeV2IpsecSAData* aQue) 
+{ 
+    if (aQue != NULL) 
+        { 
+        LinkIpsecSa(aQue); 
+        } 
+}
+