--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/ikev2lib/src/ikev2trafficselector.cpp Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,384 @@
+/*
+* Copyright (c) 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:
+*
+*/
+
+#include "ikev2trafficselector.h"
+#include "ikev2const.h"
+#include "ikev2payloads.h"
+
+TIkeV2TrafficSelector* TIkeV2TrafficSelector::NewL(const TDesC8& aIkeV2TrafficSector)
+ {
+ static const TUint16 KIpv4SelectorLength = 16;
+ static const TUint16 KIpv6SelectorLength = 48;
+
+ if (aIkeV2TrafficSector.Length() != KIpv4SelectorLength &&
+ aIkeV2TrafficSector.Length() != KIpv6SelectorLength)
+ {
+ User::Leave(KErrArgument);
+ }
+
+
+ const TTrafficSelector* selector =
+ reinterpret_cast<const TTrafficSelector*>(aIkeV2TrafficSector.Ptr());
+
+
+ TInetAddr startAddr;
+ TInetAddr endAddr;
+
+ const TUint8* addresses = selector->Addresses();
+ if ( selector->Type() == TS_IPV4_ADDR_RANGE )
+ {
+ if (aIkeV2TrafficSector.Length() != KIpv4SelectorLength)
+ {
+ User::Leave(KErrArgument);
+ }
+ TUint32 startA = *(reinterpret_cast<const TUint32*>(addresses));
+ TUint32 endA = *(reinterpret_cast<const TUint32*>(addresses + 4));
+
+ BigEndian::Put32(reinterpret_cast<TUint8*>(&startA), startA);
+ BigEndian::Put32(reinterpret_cast<TUint8*>(&endA), endA);
+
+ startAddr.SetAddress(startA);
+ endAddr.SetAddress(endA);
+
+ }
+ else
+ {
+ if (aIkeV2TrafficSector.Length() != KIpv6SelectorLength ||
+ selector->Type() != TS_IPV6_ADDR_RANGE)
+ {
+ User::Leave(KErrArgument);
+ }
+ TIp6Addr startA;
+ TIp6Addr endA;
+
+ Mem::Copy(startA.u.iAddr8, addresses, 16);
+ Mem::Copy(endA.u.iAddr8, addresses+16, 16);
+
+ startAddr.SetAddress(startA);
+ endAddr.SetAddress(endA);
+ }
+
+ TUint16 startPort = selector->StartPort();
+ BigEndian::Put16(reinterpret_cast<TUint8*>(&startPort), startPort);
+ startAddr.SetPort(startPort);
+
+ TUint16 endPort = selector->EndPort();
+ BigEndian::Put16(reinterpret_cast<TUint8*>(&endPort), endPort);
+ endAddr.SetPort(endPort);
+
+ return new (ELeave) TIkeV2TrafficSelector(startAddr, endAddr, selector->Protocol());
+ }
+
+
+TIkeV2TrafficSelector::TIkeV2TrafficSelector(TInetAddr aStartingAddress, TInetAddr aEndingAddress, TUint8 aProtocolId)
+:iStartingAddress(aStartingAddress), iEndingAddress(aEndingAddress), iProtocolId(aProtocolId)
+ {
+ __ASSERT_DEBUG(iStartingAddress.Family() == iEndingAddress.Family() &&
+ iStartingAddress.IsV4Compat() == iEndingAddress.IsV4Compat() &&
+ iStartingAddress.IsV4Mapped() == iEndingAddress.IsV4Mapped(), User::Invariant());
+
+ iMask = CalcuateMask();
+ }
+
+
+TIkeV2TrafficSelector::TIkeV2TrafficSelector(const TIkeV2TrafficSelector& aTrafficSelector)
+ {
+ iStartingAddress = aTrafficSelector.iStartingAddress;
+ iEndingAddress = aTrafficSelector.iEndingAddress;
+
+ iProtocolId = aTrafficSelector.iProtocolId;
+
+ __ASSERT_DEBUG(iStartingAddress.Family() == iEndingAddress.Family() &&
+ iStartingAddress.IsV4Compat() == iEndingAddress.IsV4Compat() &&
+ iStartingAddress.IsV4Mapped() == iEndingAddress.IsV4Mapped(), User::Invariant());
+ iMask = CalcuateMask();
+ }
+
+
+TInetAddr TIkeV2TrafficSelector::StartingAddress() const
+ {
+ return iStartingAddress;
+ }
+
+
+TInetAddr TIkeV2TrafficSelector::EndingAddress() const
+ {
+ return iEndingAddress;
+ }
+
+TInetAddr TIkeV2TrafficSelector::Mask() const
+ {
+ return iMask;
+ }
+
+TUint8 TIkeV2TrafficSelector::ProtocolId() const
+ {
+ return iProtocolId;
+ }
+
+TUint8 TIkeV2TrafficSelector::Type() const
+ {
+ __ASSERT_DEBUG(iStartingAddress.Family() == iEndingAddress.Family() &&
+ iStartingAddress.IsV4Compat() == iEndingAddress.IsV4Compat() &&
+ iStartingAddress.IsV4Mapped() == iEndingAddress.IsV4Mapped(), User::Invariant());
+
+ if (iStartingAddress.Family() == KAfInet ||
+ iStartingAddress.IsV4Compat() ||
+ iStartingAddress.IsV4Mapped())
+ {
+ return TS_IPV4_ADDR_RANGE;
+ }
+ else
+ {
+ return TS_IPV6_ADDR_RANGE;
+ }
+ }
+
+
+HBufC8* TIkeV2TrafficSelector::IdFromTsL() const
+ {
+ TInetAddr idAddr = iStartingAddress;
+ idAddr.SetPort(0);
+ TInt prefix = 0;
+ if (Type() == TS_IPV4_ADDR_RANGE)
+ {
+ TUint32 startIp = iStartingAddress.Address();
+ TUint32 endIp = iEndingAddress.Address();
+ TUint32 mask = ~(endIp ^ startIp);
+ TUint32 m = 1;
+ while ( prefix < 32 )
+ {
+ if ( mask & ( m << prefix) )
+ break;
+ prefix ++;
+ }
+ prefix = 32 - prefix;
+ idAddr = TInetAddr(startIp);
+ }
+ else
+ {
+ prefix = 128; // NOT IMPLEMENTED YET
+ }
+
+ HBufC* idString = HBufC::NewLC(512);
+ TPtr idStringPtr = idString->Des();
+ idAddr.Output(idStringPtr);
+ idStringPtr.AppendFormat(_L("/%d"), prefix);
+
+ HBufC8* idString8 = HBufC8::NewL(idString->Length());
+ TPtr8 idString8Ptr = idString8->Des();
+ idString8Ptr.Copy(*idString);
+ CleanupStack::PopAndDestroy(idString);
+
+ return idString8;
+ }
+
+TInetAddr TIkeV2TrafficSelector::CalcuateMask() const
+ {
+ TInetAddr mask;
+ if ( Type() == TS_IPV4_ADDR_RANGE )
+ {
+ TUint32 A = iStartingAddress.Address();
+ TUint32 M = iEndingAddress.Address();
+ TUint32 X = 0x80000000;
+ TUint32 Y = 0;
+ M = ~(A ^ M); //Gets the bits that are 1 in both addresses
+ for ( TInt i = 0; i < 32; ++i )
+ {
+ if ( (M & X) == 0 )
+ {
+ M &= Y;
+ break;
+ }
+ Y |= X;
+ X = (X >> 1);
+ }
+ mask.SetAddress(M);
+ }
+ else
+ {
+ TIp6Addr startAddr = iStartingAddress.Ip6Address();
+ TIp6Addr endAddr = iEndingAddress.Ip6Address();
+ TIp6Addr m;
+ Mem::FillZ(m.u.iAddr8, 16);
+
+ TUint8 c = 0xff;
+ for ( TInt i = 0; i < 16; ++i )
+ {
+ if ( c == 0xff )
+ c = (TUint8)(~(startAddr.u.iAddr8[i] ^ endAddr.u.iAddr8[i])); // Convert range to mask
+ if ( (c != 0) && (c != 0xff) )
+ {
+ TUint8 z = 0x80;
+ TUint8 w = 0;
+ for ( TInt j = 0; j < 8; ++j )
+ {
+ if ( (c & z) == 0 )
+ {
+ c &= w;
+ break;
+ }
+ w |= z;
+ z = (TUint8)(z >> 1);
+ }
+ m.u.iAddr8[i] = c;
+ c = 0;
+ }
+ else
+ {
+ m.u.iAddr8[i] = c;
+ }
+ }
+ mask.SetAddress(m);
+ }
+ return mask;
+ }
+
+bool TIkeV2TrafficSelector::operator>(const TIkeV2TrafficSelector& aOtherSelector) const
+ {
+ if (Type() != aOtherSelector.Type())
+ {
+ //types do not match.
+ return false;
+ }
+
+ if (operator==(aOtherSelector))
+ {
+ //selectors are equal
+ return false;
+ }
+
+ return operator>=(aOtherSelector);
+ }
+
+
+bool TIkeV2TrafficSelector::operator<(const TIkeV2TrafficSelector& aOtherSelector) const
+ {
+ if (operator==(aOtherSelector))
+ {
+ //selectors are equal
+ return false;
+ }
+
+ //The operator
+ return operator<=(aOtherSelector);
+ }
+
+bool TIkeV2TrafficSelector::operator!=(const TIkeV2TrafficSelector& aOtherSelector) const
+ {
+ return !operator==(aOtherSelector);
+ }
+
+bool TIkeV2TrafficSelector::operator==(const TIkeV2TrafficSelector& aOtherSelector) const
+ {
+ return (iStartingAddress == aOtherSelector.iStartingAddress &&
+ iEndingAddress == aOtherSelector.iEndingAddress);
+ }
+
+bool TIkeV2TrafficSelector::operator>=(const TIkeV2TrafficSelector& aOtherSelector) const
+ {
+ if (Type() != aOtherSelector.Type())
+ {
+ //types do not match.
+ return false;
+ }
+
+ if (operator==(aOtherSelector))
+ {
+ //selectors are equal
+ return true;
+ }
+
+ return !operator<(aOtherSelector);
+ }
+
+bool TIkeV2TrafficSelector::operator<=(const TIkeV2TrafficSelector& aOtherSelector) const
+ {
+ if (Type() != aOtherSelector.Type())
+ {
+ //types do not match.
+ return false;
+ }
+
+ if (operator==(aOtherSelector))
+ {
+ //selectors are equal
+ return true;
+ }
+
+ if (iStartingAddress.Port() < aOtherSelector.iStartingAddress.Port() ||
+ iEndingAddress.Port() > aOtherSelector.iEndingAddress.Port())
+ {
+ //Port range of this is bigger
+ return false;
+ }
+
+ if (Type() == TS_IPV4_ADDR_RANGE)
+ {
+ if (iStartingAddress.Address() >= aOtherSelector.iStartingAddress.Address() &&
+ iEndingAddress.Address() <= aOtherSelector.iEndingAddress.Address())
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ __ASSERT_DEBUG(Type() == TS_IPV6_ADDR_RANGE, User::Invariant());
+
+ const TIp6Addr& thisStart = iStartingAddress.Ip6Address();
+ const TIp6Addr& thisEnd = iEndingAddress.Ip6Address();
+
+ const TIp6Addr& otherStart = aOtherSelector.iStartingAddress.Ip6Address();
+ const TIp6Addr& otherEnd = aOtherSelector.iEndingAddress.Ip6Address();
+
+ TInt i;
+ for (i = 0; i < 4; i++)
+ {
+ if (thisStart.u.iAddr32[i] > otherStart.u.iAddr32[i])
+ {
+ //this start address is bigger
+ break;
+ }
+ else if (thisStart.u.iAddr32[i] < otherStart.u.iAddr32[i])
+ {
+ //this start address is smaller.
+ return false;
+ }
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ if (thisEnd.u.iAddr32[i] < otherEnd.u.iAddr32[i])
+ {
+ //this end address is smaller
+ break;
+ }
+ else if (thisEnd.u.iAddr32[i] > otherEnd.u.iAddr32[i])
+ {
+ //this end address is bigger
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+