--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networksecurity/ipsec/ipsec6/src/epdb.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,448 @@
+// Copyright (c) 2006-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:
+// epdb.cpp - IPSEC Endpoint Database implementation
+// @internalComponent for IPSEC
+//
+
+#include "sa_spec.h"
+#include "ipaddress.h"
+#include "epdb.h"
+#include "ipseclog.h"
+
+class CEndPoint : public CIpsecReferenceCountObject
+ /**
+ * Storage location for internet address with scope id.
+ *
+ * This object is always a member of some collection of
+ * addresses via the RCircularList. The collection may
+ * contain only this object. The membership in the
+ * collection does not required reference counting -- when
+ * object is deleted, it is removed from the collection
+ * (and added to a collection containing only the self).
+ */
+ {
+protected:
+ ~CEndPoint();
+public:
+ CEndPoint(const TIp6Addr &aAddr, const TUint32 aScope);
+ CEndPoint(RCircularList &aList, TUint aLength);
+ static CEndPoint *New(RCircularList &aList, const TDesC &aName);
+ static CEndPoint &Cast(RCircularList &aList);
+ TBool MatchingName(const TDesC &aName);
+
+ RCircularList iList; //< Maintain a collection of addresses.
+ TIpAddress iAddr; //< Address and scope id.
+
+ //
+ // *WARNING* *WARNING* *WARNING*
+ // What now follows, is the TLitC8 structure.
+ // The extra space is allocated only, if iTypeLength
+ // is non-zero.
+ //
+ // Why this TLitC8 "hack" instead of traditional
+ // C construct with a "length" member and "fake buf[1]"?
+ //
+ // As far as layout, this is exactly the same. The TLitC8
+ // "hack" only forces a Symbian specific layout. When a
+ // descriptor is needed, it doesn't need to be constructed,
+ // it's already existing and just returning a reference
+ // to iTypeLength as TLitC8 is sufficient.
+ //
+ const TUint iTypeLength;
+
+ inline const TDesC8 &Name() const { return ((TLitC8<1> &)iTypeLength)(); }
+ inline TBool IsNamed() const { return iTypeLength != 0; }
+ };
+
+//
+// CEndPoint implementation //
+//
+
+CEndPoint::CEndPoint(const TIp6Addr &aAddr, const TUint32 aScope) : iAddr(aAddr, aScope), iTypeLength(0)
+ {
+ }
+
+CEndPoint::CEndPoint(RCircularList &aList, TUint aLength) : iTypeLength(aLength)
+ {
+ aList.Attach(iList);
+ }
+
+CEndPoint::~CEndPoint()
+ {
+ iList.Detach();
+ }
+
+CEndPoint &CEndPoint::Cast(RCircularList &aList)
+ {
+ return *((CEndPoint *)((char *)(&aList) - _FOFF(CEndPoint, iList)));
+ }
+
+
+CEndPoint *CEndPoint::New(RCircularList &aList, const TDesC &aName)
+ {
+ const TUint len = aName.Length();
+ CEndPoint *ep = new (len) CEndPoint(aList, len);
+ if (ep)
+ {
+ // See _LIT and TLitC for this initializer!!!
+ TPtr8(&((TLitC8<1> &)ep->iTypeLength).iBuf[0], len).Copy(aName);
+ }
+ return ep;
+ }
+
+
+TBool CEndPoint::MatchingName(const TDesC &aName)
+ /**
+ * Test if the end point name matches.
+ *
+ * This is not simple compare, but
+ *
+ * - unnamed end point (name length == 0) does not match empty aName
+ * - comparison is made only between lower 8 bits of each character (name should only contain ASCII!)
+ *
+ * @param aName The name to be compared.
+ */
+ {
+ TInt i = aName.Length();
+ if (iTypeLength == 0 || (TUint)i != iTypeLength)
+ return EFalse;
+ const TText *s = aName.Ptr();
+ const TText8 *p = Name().Ptr();
+ while (--i >= 0)
+ {
+ if (s[i] != p[i])
+ return EFalse;
+ }
+ return ETrue;
+ }
+
+//
+// RIpAddress implementation //
+//
+
+RIpAddress::RIpAddress(const RIpAddress &aAddr)
+ /**
+ * Copy constructor.
+ *
+ * Update the reference count of the copied object.
+ */
+ {
+ if ((iAddr = aAddr.iAddr) != NULL)
+ iAddr->Open();
+ }
+
+RIpAddress & RIpAddress::operator=(const RIpAddress &aAddr)
+ /**
+ * Assign operator.
+ *
+ * Close previous content and update the reference count
+ * of the assigned object.
+ */
+ {
+ if (this != &aAddr) // Only need do something if not assigning to self.
+ {
+ Close();
+ if ((iAddr = aAddr.iAddr) != NULL)
+ iAddr->Open();
+ }
+ return *this;
+ }
+
+
+RIpAddress::~RIpAddress()
+ /**
+ * Destructor is implicit Close.
+ */
+ {
+ Close();
+ }
+
+void RIpAddress::Close()
+ /**
+ * Detach address from the handle.
+ */
+ {
+ if (iAddr)
+ {
+ iAddr->Close();
+ iAddr = NULL;
+ }
+ }
+
+TInt RIpAddress::Open(REndPoints &aMgr, const TDesC &aName)
+ /**
+ * Find an existing named end point and attach.
+ *
+ * @param aMgr The EndPoint Collection
+ * @param aName The EndPoint Name
+ *
+ * @return KErrNone on success, and KErrNotFound if endpoint is not defined.
+ */
+ {
+ Close(); // Detach previous, if any present.
+ TCircularListIter iter(aMgr);
+ RCircularList *r;
+ while ((r = iter++) != NULL)
+ {
+ CEndPoint &p = CEndPoint::Cast(*r);
+ if (p.MatchingName(aName))
+ {
+ // An additional reference to an existing named
+ // address, the reference count needs to be incremented.
+ p.Open();
+ iAddr = &p;
+ return KErrNone;
+ }
+ }
+ return KErrNotFound;
+ }
+
+TInt RIpAddress::Open(REndPoints &aMgr, const TIpAddress &aAddr)
+ /**
+ * Find or create unnamed end point and attach.
+ *
+ * @param aMgr The EndPoint Collection
+ * @param aAddr The EndPoint address
+ *
+ * @return KErrNone when success, and KErrNoMemory if end point allocation fails.
+ */
+ {
+ Close(); // Detach previous, if any present.
+ TCircularListIter iter(aMgr);
+ RCircularList *r;
+ while ((r = iter++) != NULL)
+ {
+ CEndPoint &p = CEndPoint::Cast(*r);
+
+ // *note* currently TIpAddress == operator treats iScope==0 as
+ // a wild card. That is not the correct semantic here.
+ // The values need to match bit by bit..
+ if (!p.IsNamed () && p.iAddr.IsEqual(aAddr) && p.iAddr.iScope == aAddr.iScope)
+ {
+ // An additional reference to an existing unnamed
+ // address, the reference count needs to be incremented.
+ p.Open();
+ iAddr = &p;
+ return KErrNone;
+ }
+ }
+ // Create a new unnamed address. The initial reference
+ // from the contruction corresponds to the RIpAddress
+ // handle. The membership in the circular list is not
+ // counted as a reference.
+ iAddr = new CEndPoint(aMgr, 0);
+ if (iAddr == NULL)
+ return KErrNoMemory;
+ iAddr->iAddr = aAddr;
+ return KErrNone;
+ }
+
+TInt RIpAddress::Open(REndPoints &aMgr, const TInetAddr &aAddr)
+ {
+ TIpAddress addr(aAddr);
+ return Open(aMgr, addr);
+ }
+
+TInt RIpAddress::Open(REndPoints &aMgr, const TDesC &aName, const TIpAddress &aAddr, TInt aOptional)
+ /**
+ * Find or create named end point and attach.
+ *
+ * Search for the named enpoint and attach it if found. If not found,
+ * create a new end point into the end point collection.
+ *
+ * The aAddr is the initial value for the new end point. If the end
+ * already exists, the content is changed to aAddr, if aOptional is
+ * non-zero. Otherwise old end point content is not changed.
+ *
+ * @param aMgr The EndPoint Collection
+ * @param aName The EndPoint Name
+ * @param aAddr The new address of the end point (see aOptional)
+ * @param aOptional Controls whether existing end point address is overwritten.
+ *
+ * @return KErrNone if success, and KErrNoMemory if endpoint cannot be allocated.
+ */
+ {
+ if (Open(aMgr, aName) != KErrNone)
+ {
+ // Create a new named end point. The initial reference
+ // from the contruction corresponds to the RIpAddress
+ // handle. The membership in the circular list is not
+ // counted as a reference.
+ CEndPoint *p = CEndPoint::New(aMgr, aName);
+ if (p == NULL)
+ return KErrNoMemory;
+ iAddr = p;
+ aOptional = 0;
+ }
+ if (!aOptional)
+ {
+ iAddr->iAddr = aAddr;
+ }
+ return KErrNone;
+ }
+
+
+
+TInt RIpAddress::Set(const TIp6Addr &aAddr, TUint32 aScopeId)
+ /**
+ * Set content to given internet address.
+ *
+ * This cannot be used to change address content of an
+ * existing named or internal end point. If there is an
+ * existing CEndPoint which is shared by someone else
+ * (reference count > 0 or a member of collection
+ * with other objects), then this detaches from that
+ * end point and allocates a new private CEndPoint
+ * for the handle.
+ *
+ * This method is tailored for fast operation when
+ * the address information from the packet or flow
+ * needs to be packed into RIpAddress. By preallocating
+ * this handle and never sharing the content, the
+ * Set operation is a simple address copy and no
+ * memory allocation.
+ *
+ * @param aAddr The raw IPv6 address
+ * @param aScopeId The scope id of the address
+ *
+ * @return KErrNone or KErrNoMemory.
+ */
+ {
+ if (iAddr == NULL || iAddr->IsShared())
+ {
+ // The End Point does not exist, or is shared in some way. Need to
+ // allocate a new object for this handle.
+
+ Close(); // Release previous object.
+ iAddr = new CEndPoint(aAddr, aScopeId);
+ if (iAddr == NULL)
+ return KErrNoMemory;
+ }
+ else
+ {
+ if (!iAddr->iList.IsDetached())
+ {
+ // The object is a member of non-empty collection. However,
+ // because this reference is the only reference to it,
+ // closing would only delete the object. Might as well
+ // just detach it from the collection and reuse the
+ // CEndPoint as is. [this is "just in case" branch --
+ // the normal intended usage pattern should not make
+ // CEndPoint of this handle to be a member of any
+ // collection!]
+ iAddr->iList.Detach();
+ }
+ iAddr->iAddr.SetAddress(aAddr, aScopeId);
+ }
+ return KErrNone;
+ }
+
+TInt RIpAddress::Set(const TInetAddr &aAddr)
+ /**
+ * Set content to given internet address.
+ *
+ * See the other Set.
+ *
+ * @param aAddr The internet address in IPv6 format.
+ */
+ {
+ return Set(aAddr.Ip6Address(), aAddr.Scope());
+ }
+
+const TIpAddress& RIpAddress::operator()() const
+ /**
+ * Returns a reference to the contained IP address.
+ *
+ * This reference is only valid as long as handle is open. It must not
+ * be used after the handle is closed.
+ *
+ * Always succeeds, and returns all zeroes address, if handle is not open.
+ *
+ * @return The Address.
+ */
+ {
+ // This is actually
+ // static const TIpAddress none;
+ // but which cannot be used because TIpAddress has a constructor
+ // and it would result "ipsec6.prt has initialized data" error
+ // for target build.
+ static const char none[sizeof(TIpAddress)] = {0 };
+
+ return iAddr ? iAddr->iAddr : reinterpret_cast<const TIpAddress &>(none);
+ }
+
+TBool RIpAddress::IsNamed() const
+ {
+ return iAddr ? iAddr->IsNamed() : EFalse;
+ }
+
+const TDesC8 &RIpAddress::Name() const
+ {
+ return IsNamed() ? iAddr->Name() : KNullDesC8();
+ }
+
+
+//
+// REndPoints implementation //
+//
+//
+// Debug only //
+//
+
+#ifdef _LOG
+
+class TAddressBuf : public TBuf<70>
+ {
+public:
+ TAddressBuf(const TIpAddress &aAddr);
+ };
+
+TAddressBuf::TAddressBuf(const TIpAddress &aAddr)
+ {
+ TInetAddr addr(aAddr, 0);
+ addr.SetScope(aAddr.iScope);
+ addr.OutputWithScope(*this);
+ }
+
+void REndPoints::LogPrint(const TDesC &aFormat) const
+ /**
+ * Print the current set of end points into IPSEC Log file.
+ *
+ * The format string must contain exactly two %S format
+ * controls. The first is used for the name and the second
+ * for the currently assigned address.
+ *
+ * @param aFormat The print format.
+ */
+ {
+ _LIT(KUnnamed, "<internal>");
+
+ TCircularListIter iter(*this);
+ RCircularList *r;
+ while ((r = iter++) != NULL)
+ {
+ const CEndPoint &n = CEndPoint::Cast(*r);
+ TAddressBuf addr(n.iAddr);
+ if (n.IsNamed())
+ {
+ TBuf<100> name;
+ name.Copy(n.Name());
+ Log::Printf(aFormat, &name, &addr);
+ }
+ else
+ Log::Printf(aFormat, &KUnnamed(), &addr);
+ }
+ }
+#endif
+