vpnengine/ikev2lib/src/Ikev2Config.cpp
changeset 0 33413c0669b9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev2lib/src/Ikev2Config.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,273 @@
+/*
+* Copyright (c) 2003-2009 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: This class is used to handle IKEv2 configuration payload attributes.
+*
+*/
+
+#include "ikedebug.h"
+#include "ikev2config.h"
+#include "ikev2payloads.h"
+#include "ikev2const.h"
+#include "internaladdress.h"
+#include "ipsecselectors.h"
+#include "ikev2acquire.h"
+#include "ikev2trafficselector.h"
+
+CIkev2Config* CIkev2Config::NewL(CIkev2Acquire* aAcquire, TInetAddr* aRemoteIp)
+{
+	CIkev2Config* Config = new (ELeave)CIkev2Config();
+	CleanupStack::PushL(Config);
+	Config->ConstructL(aAcquire, aRemoteIp);
+	CleanupStack::Pop(Config);		
+	return Config;
+}
+
+CIkev2Config::~CIkev2Config() 
+    {
+    delete iCp; 
+    }
+
+
+TBool CIkev2Config::ProcessCpL(TCPPayloadIkev2* Cp)
+{
+    ASSERT(Cp);
+   //
+   // Process received CP payload according to message type     
+   // If CP request is going and reply received parse attributes to get
+   // Virtual IP and possible DNS addresses. If INTERNAL_ADDRESS_EXPIRY
+   // present save it into object too. (used as IKE SA lifetime).
+   // If CP request received sanity check attributes (CFG_REPLY has
+   // already been built on constructor ConstructL().
+   // All other messages (CFG_SET and CFG_ACK) are silently discarded
+   //
+    TBool Status = EFalse;
+	
+    if ( (Cp->GetCFGType() == CFG_REQUEST) || (Cp->GetCFGType() == CFG_REPLY) )
+	{
+		Status = ETrue;
+
+		TInt AttrLth;
+		TUint32   Ipv4Addr;
+		TIp6Addr  Ipv6Addr;    //IPV6 raw address
+		TDataAttributes* Attribute = Cp->Attributes();		
+		TInt Lth = (TInt)(TPayloadIkev2::Cast(Cp)->GetLength()) - TCPPayloadIkev2::Size();
+		
+		while ( Status && Lth )
+		{
+			AttrLth = (TInt)Attribute->GetValue();
+			switch ( Attribute->GetType() )
+			{
+				
+				case INTERNAL_IP4_ADDRESS:
+					if ( (AttrLth == 0) || (AttrLth == 4) )
+					{
+					   if (AttrLth == 4)
+					   {
+						  Ipv4Addr = GET32(Attribute->Data()); 
+						  iVIP.iVPNIfAddr.SetAddress(Ipv4Addr);
+					   }	   
+					}	
+					else Status = EFalse;	
+					break;
+
+				case INTERNAL_IP4_DNS:
+					if ( (AttrLth == 0) || (AttrLth == 4) )
+					{
+						if (AttrLth == 4)
+						{	
+						   Ipv4Addr = GET32(Attribute->Data());
+						   
+						   //Only two DNS server addresses supported
+						   if (iVIP.iVPNIfDNS1.IsUnspecified())
+						       {
+						       iVIP.iVPNIfDNS1.SetAddress(Ipv4Addr);
+						       }
+						   else if (iVIP.iVPNIfDNS2.IsUnspecified())
+						       {
+						       iVIP.iVPNIfDNS2.SetAddress(Ipv4Addr);
+						       }
+						}
+					}	
+					else Status = EFalse;	
+					break;
+
+				case INTERNAL_ADDRESS_EXPIRY:
+					if ( (AttrLth == 0) || (AttrLth == 4) )
+					{
+						if ( AttrLth == 4 )
+						{
+						   iAddressExpiry = GET32(Attribute->Data());
+						}	
+					}	
+					else Status = EFalse;	
+					break;
+					
+				case INTERNAL_IP6_ADDRESS:
+					if ( (AttrLth == 0) || (AttrLth == 16) )
+					{
+						if ( (AttrLth == 16))
+						{
+						   Mem::Copy(&Ipv6Addr.u.iAddr8, Attribute->Data(), sizeof(Ipv6Addr.u.iAddr8));
+						   iVIP.iVPNIfAddr.SetAddress(Ipv6Addr);
+						}	   
+					}	
+					else Status = EFalse;
+					break;
+					
+				default:
+					//
+					// All other parameters are just ignored
+					//
+                    break;
+					
+			}
+
+			AttrLth += Attribute->Size();
+			if ( Lth < AttrLth )
+			{
+			   Status = EFalse;	
+			   break;  // Error
+			}	 
+			else Lth -= AttrLth;
+			
+			Attribute = Attribute->Next();			
+		
+		}
+		
+		if ( !Status &&  Cp->GetCFGType() != CFG_REPLY)
+		{
+           delete iCp;
+           iCp = NULL;
+		}	
+	}
+	
+	return Status;
+}
+
+void CIkev2Config::ConstructL(CIkev2Acquire* aAcquire, TInetAddr* aRemoteIp)
+{
+    ASSERT(aAcquire);
+   //
+   // Build either Config Payload Request or Reply depending on 
+   // CIkev2Acquire object "role".
+   // If CIkev2Acquire is a request (=not response) build CFG_REQUEST 
+   // If CIkev2Acquire is a response) build CFG_REPLY and replace initiator
+   // Traffic selector in CIkev2Acquire with Traffic selector containing
+   // "dummy"  Virtual IP address built from CIkev2Acquire ID.
+   //
+	iCp = HBufC8::NewL(80);
+	TDataAttributes* Attributes = reinterpret_cast<TDataAttributes*>(const_cast<TUint8*>(iCp->Ptr()));
+	TInt AttrLth = 0;
+
+    if ( !aAcquire->Response() )
+	{
+        iCpType = CFG_REQUEST;
+		AttrLth += AddAttribute(Attributes, INTERNAL_IP4_ADDRESS, 0, NULL);
+		Attributes = Attributes->Next();
+		AttrLth += AddAttribute(Attributes, INTERNAL_IP4_DNS, 0, NULL);
+	}
+	else
+	{
+		//
+		// Build "dummy" virtual IPv4 
+		//
+        iCpType = CFG_REPLY;
+		TUint32 virtualIp = aAcquire->Id();
+		if ( !aRemoteIp ||
+		     ((aRemoteIp->Family() == KAfInet6) && !aRemoteIp->IsV4Mapped() && !aRemoteIp->IsV4Compat()))
+		{
+		   //
+		   // "Dummy" virtual IPv4 is created from CIkev2Acquire object Id
+		   // data. The address format is the following: 10.x.y.z where bit 1 is always 0
+		   //
+		   virtualIp  = aAcquire->Id();
+		   virtualIp &= 0xfdfdfd;
+		   virtualIp |= 0x0a000000;
+		}
+		else
+		{
+		   //
+		   // "Dummy" virtual IPv4 is created from original peer
+		   // address as follows:
+		   // Original address: x.y.z.w ==> Virtual IP: 10.y.z.w
+		   // If original address: 10.y.z.w ==> Virtual IP: 172.y.z.w
+		   //
+			virtualIp = aRemoteIp->Address();
+			if ( (virtualIp & 0xff000000 ) != 0x0a000000)
+				 virtualIp = (virtualIp & 0xffffff) | 0x0a000000;
+			else virtualIp = (virtualIp & 0xffffff) | 0xac000000;			
+		}	
+		TInetAddr Ipv4Addr;
+		Ipv4Addr.SetAddress(virtualIp);
+		virtualIp = ByteOrder::Swap32(virtualIp);
+		AttrLth += AddAttribute(Attributes, INTERNAL_IP4_ADDRESS, 4, (TUint8*)&virtualIp);
+
+		//
+		// Replace original Initiator Traffic selector with new based
+		// on "virtualIp"
+		//
+		__ASSERT_DEBUG(aAcquire->TS_i().Count() > 0, User::Invariant());
+		TUint8 Protocol = aAcquire->TS_i()[0].ProtocolId();
+		
+		CArrayFix<TIkeV2TrafficSelector>* newSelectors = 
+                            new (ELeave) CArrayFixFlat<TIkeV2TrafficSelector>(1);
+		CleanupStack::PushL(newSelectors);
+		TIkeV2TrafficSelector selector(Ipv4Addr, Ipv4Addr, Protocol);
+		newSelectors->AppendL(selector);
+		aAcquire->ReplaceTS_i(newSelectors);
+		CleanupStack::Pop(newSelectors);		
+	}	
+    iCp->Des().SetLength(AttrLth);	
+}
+
+TInt CIkev2Config::AddAttribute(TDataAttributes* aAttr, TUint8 aType, TInt aLth, TUint8* aData)
+{
+    ASSERT(aAttr);
+    //
+	// Set R-Bit zero by adding attribute as variable length attribute 
+	//
+	aAttr->SetVariable();
+	aAttr->SetType(aType);	
+	aAttr->SetValue((TUint16)aLth);	
+	if ( aLth && aData )
+		Mem::Copy(aAttr->Data(), aData, aLth);
+
+	return (aLth + aAttr->Size());
+}
+
+TPtrC8 CIkev2Config::Cp() const 
+    { 
+    __ASSERT_DEBUG(iCp != NULL, User::Invariant());    
+    return *iCp;
+    }
+
+
+TUint8 CIkev2Config::CpType()const
+    {
+    return iCpType;
+    }
+
+TUint32 CIkev2Config::ExpireTime() const 
+    { 
+    return iAddressExpiry;
+    }
+
+
+TVPNAddress CIkev2Config::VirtualIp()
+    {
+    TVPNAddress Vip = iVIP;
+    iVIP = TVPNAddress(); 
+    return Vip;
+    }
+