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