|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // epdb.cpp - IPSEC Endpoint Database implementation |
|
15 // @internalComponent for IPSEC |
|
16 // |
|
17 |
|
18 #include "sa_spec.h" |
|
19 #include "ipaddress.h" |
|
20 #include "epdb.h" |
|
21 #include "ipseclog.h" |
|
22 |
|
23 class CEndPoint : public CIpsecReferenceCountObject |
|
24 /** |
|
25 * Storage location for internet address with scope id. |
|
26 * |
|
27 * This object is always a member of some collection of |
|
28 * addresses via the RCircularList. The collection may |
|
29 * contain only this object. The membership in the |
|
30 * collection does not required reference counting -- when |
|
31 * object is deleted, it is removed from the collection |
|
32 * (and added to a collection containing only the self). |
|
33 */ |
|
34 { |
|
35 protected: |
|
36 ~CEndPoint(); |
|
37 public: |
|
38 CEndPoint(const TIp6Addr &aAddr, const TUint32 aScope); |
|
39 CEndPoint(RCircularList &aList, TUint aLength); |
|
40 static CEndPoint *New(RCircularList &aList, const TDesC &aName); |
|
41 static CEndPoint &Cast(RCircularList &aList); |
|
42 TBool MatchingName(const TDesC &aName); |
|
43 |
|
44 RCircularList iList; //< Maintain a collection of addresses. |
|
45 TIpAddress iAddr; //< Address and scope id. |
|
46 |
|
47 // |
|
48 // *WARNING* *WARNING* *WARNING* |
|
49 // What now follows, is the TLitC8 structure. |
|
50 // The extra space is allocated only, if iTypeLength |
|
51 // is non-zero. |
|
52 // |
|
53 // Why this TLitC8 "hack" instead of traditional |
|
54 // C construct with a "length" member and "fake buf[1]"? |
|
55 // |
|
56 // As far as layout, this is exactly the same. The TLitC8 |
|
57 // "hack" only forces a Symbian specific layout. When a |
|
58 // descriptor is needed, it doesn't need to be constructed, |
|
59 // it's already existing and just returning a reference |
|
60 // to iTypeLength as TLitC8 is sufficient. |
|
61 // |
|
62 const TUint iTypeLength; |
|
63 |
|
64 inline const TDesC8 &Name() const { return ((TLitC8<1> &)iTypeLength)(); } |
|
65 inline TBool IsNamed() const { return iTypeLength != 0; } |
|
66 }; |
|
67 |
|
68 // |
|
69 // CEndPoint implementation // |
|
70 // |
|
71 |
|
72 CEndPoint::CEndPoint(const TIp6Addr &aAddr, const TUint32 aScope) : iAddr(aAddr, aScope), iTypeLength(0) |
|
73 { |
|
74 } |
|
75 |
|
76 CEndPoint::CEndPoint(RCircularList &aList, TUint aLength) : iTypeLength(aLength) |
|
77 { |
|
78 aList.Attach(iList); |
|
79 } |
|
80 |
|
81 CEndPoint::~CEndPoint() |
|
82 { |
|
83 iList.Detach(); |
|
84 } |
|
85 |
|
86 CEndPoint &CEndPoint::Cast(RCircularList &aList) |
|
87 { |
|
88 return *((CEndPoint *)((char *)(&aList) - _FOFF(CEndPoint, iList))); |
|
89 } |
|
90 |
|
91 |
|
92 CEndPoint *CEndPoint::New(RCircularList &aList, const TDesC &aName) |
|
93 { |
|
94 const TUint len = aName.Length(); |
|
95 CEndPoint *ep = new (len) CEndPoint(aList, len); |
|
96 if (ep) |
|
97 { |
|
98 // See _LIT and TLitC for this initializer!!! |
|
99 TPtr8(&((TLitC8<1> &)ep->iTypeLength).iBuf[0], len).Copy(aName); |
|
100 } |
|
101 return ep; |
|
102 } |
|
103 |
|
104 |
|
105 TBool CEndPoint::MatchingName(const TDesC &aName) |
|
106 /** |
|
107 * Test if the end point name matches. |
|
108 * |
|
109 * This is not simple compare, but |
|
110 * |
|
111 * - unnamed end point (name length == 0) does not match empty aName |
|
112 * - comparison is made only between lower 8 bits of each character (name should only contain ASCII!) |
|
113 * |
|
114 * @param aName The name to be compared. |
|
115 */ |
|
116 { |
|
117 TInt i = aName.Length(); |
|
118 if (iTypeLength == 0 || (TUint)i != iTypeLength) |
|
119 return EFalse; |
|
120 const TText *s = aName.Ptr(); |
|
121 const TText8 *p = Name().Ptr(); |
|
122 while (--i >= 0) |
|
123 { |
|
124 if (s[i] != p[i]) |
|
125 return EFalse; |
|
126 } |
|
127 return ETrue; |
|
128 } |
|
129 |
|
130 // |
|
131 // RIpAddress implementation // |
|
132 // |
|
133 |
|
134 RIpAddress::RIpAddress(const RIpAddress &aAddr) |
|
135 /** |
|
136 * Copy constructor. |
|
137 * |
|
138 * Update the reference count of the copied object. |
|
139 */ |
|
140 { |
|
141 if ((iAddr = aAddr.iAddr) != NULL) |
|
142 iAddr->Open(); |
|
143 } |
|
144 |
|
145 RIpAddress & RIpAddress::operator=(const RIpAddress &aAddr) |
|
146 /** |
|
147 * Assign operator. |
|
148 * |
|
149 * Close previous content and update the reference count |
|
150 * of the assigned object. |
|
151 */ |
|
152 { |
|
153 if (this != &aAddr) // Only need do something if not assigning to self. |
|
154 { |
|
155 Close(); |
|
156 if ((iAddr = aAddr.iAddr) != NULL) |
|
157 iAddr->Open(); |
|
158 } |
|
159 return *this; |
|
160 } |
|
161 |
|
162 |
|
163 RIpAddress::~RIpAddress() |
|
164 /** |
|
165 * Destructor is implicit Close. |
|
166 */ |
|
167 { |
|
168 Close(); |
|
169 } |
|
170 |
|
171 void RIpAddress::Close() |
|
172 /** |
|
173 * Detach address from the handle. |
|
174 */ |
|
175 { |
|
176 if (iAddr) |
|
177 { |
|
178 iAddr->Close(); |
|
179 iAddr = NULL; |
|
180 } |
|
181 } |
|
182 |
|
183 TInt RIpAddress::Open(REndPoints &aMgr, const TDesC &aName) |
|
184 /** |
|
185 * Find an existing named end point and attach. |
|
186 * |
|
187 * @param aMgr The EndPoint Collection |
|
188 * @param aName The EndPoint Name |
|
189 * |
|
190 * @return KErrNone on success, and KErrNotFound if endpoint is not defined. |
|
191 */ |
|
192 { |
|
193 Close(); // Detach previous, if any present. |
|
194 TCircularListIter iter(aMgr); |
|
195 RCircularList *r; |
|
196 while ((r = iter++) != NULL) |
|
197 { |
|
198 CEndPoint &p = CEndPoint::Cast(*r); |
|
199 if (p.MatchingName(aName)) |
|
200 { |
|
201 // An additional reference to an existing named |
|
202 // address, the reference count needs to be incremented. |
|
203 p.Open(); |
|
204 iAddr = &p; |
|
205 return KErrNone; |
|
206 } |
|
207 } |
|
208 return KErrNotFound; |
|
209 } |
|
210 |
|
211 TInt RIpAddress::Open(REndPoints &aMgr, const TIpAddress &aAddr) |
|
212 /** |
|
213 * Find or create unnamed end point and attach. |
|
214 * |
|
215 * @param aMgr The EndPoint Collection |
|
216 * @param aAddr The EndPoint address |
|
217 * |
|
218 * @return KErrNone when success, and KErrNoMemory if end point allocation fails. |
|
219 */ |
|
220 { |
|
221 Close(); // Detach previous, if any present. |
|
222 TCircularListIter iter(aMgr); |
|
223 RCircularList *r; |
|
224 while ((r = iter++) != NULL) |
|
225 { |
|
226 CEndPoint &p = CEndPoint::Cast(*r); |
|
227 |
|
228 // *note* currently TIpAddress == operator treats iScope==0 as |
|
229 // a wild card. That is not the correct semantic here. |
|
230 // The values need to match bit by bit.. |
|
231 if (!p.IsNamed () && p.iAddr.IsEqual(aAddr) && p.iAddr.iScope == aAddr.iScope) |
|
232 { |
|
233 // An additional reference to an existing unnamed |
|
234 // address, the reference count needs to be incremented. |
|
235 p.Open(); |
|
236 iAddr = &p; |
|
237 return KErrNone; |
|
238 } |
|
239 } |
|
240 // Create a new unnamed address. The initial reference |
|
241 // from the contruction corresponds to the RIpAddress |
|
242 // handle. The membership in the circular list is not |
|
243 // counted as a reference. |
|
244 iAddr = new CEndPoint(aMgr, 0); |
|
245 if (iAddr == NULL) |
|
246 return KErrNoMemory; |
|
247 iAddr->iAddr = aAddr; |
|
248 return KErrNone; |
|
249 } |
|
250 |
|
251 TInt RIpAddress::Open(REndPoints &aMgr, const TInetAddr &aAddr) |
|
252 { |
|
253 TIpAddress addr(aAddr); |
|
254 return Open(aMgr, addr); |
|
255 } |
|
256 |
|
257 TInt RIpAddress::Open(REndPoints &aMgr, const TDesC &aName, const TIpAddress &aAddr, TInt aOptional) |
|
258 /** |
|
259 * Find or create named end point and attach. |
|
260 * |
|
261 * Search for the named enpoint and attach it if found. If not found, |
|
262 * create a new end point into the end point collection. |
|
263 * |
|
264 * The aAddr is the initial value for the new end point. If the end |
|
265 * already exists, the content is changed to aAddr, if aOptional is |
|
266 * non-zero. Otherwise old end point content is not changed. |
|
267 * |
|
268 * @param aMgr The EndPoint Collection |
|
269 * @param aName The EndPoint Name |
|
270 * @param aAddr The new address of the end point (see aOptional) |
|
271 * @param aOptional Controls whether existing end point address is overwritten. |
|
272 * |
|
273 * @return KErrNone if success, and KErrNoMemory if endpoint cannot be allocated. |
|
274 */ |
|
275 { |
|
276 if (Open(aMgr, aName) != KErrNone) |
|
277 { |
|
278 // Create a new named end point. The initial reference |
|
279 // from the contruction corresponds to the RIpAddress |
|
280 // handle. The membership in the circular list is not |
|
281 // counted as a reference. |
|
282 CEndPoint *p = CEndPoint::New(aMgr, aName); |
|
283 if (p == NULL) |
|
284 return KErrNoMemory; |
|
285 iAddr = p; |
|
286 aOptional = 0; |
|
287 } |
|
288 if (!aOptional) |
|
289 { |
|
290 iAddr->iAddr = aAddr; |
|
291 } |
|
292 return KErrNone; |
|
293 } |
|
294 |
|
295 |
|
296 |
|
297 TInt RIpAddress::Set(const TIp6Addr &aAddr, TUint32 aScopeId) |
|
298 /** |
|
299 * Set content to given internet address. |
|
300 * |
|
301 * This cannot be used to change address content of an |
|
302 * existing named or internal end point. If there is an |
|
303 * existing CEndPoint which is shared by someone else |
|
304 * (reference count > 0 or a member of collection |
|
305 * with other objects), then this detaches from that |
|
306 * end point and allocates a new private CEndPoint |
|
307 * for the handle. |
|
308 * |
|
309 * This method is tailored for fast operation when |
|
310 * the address information from the packet or flow |
|
311 * needs to be packed into RIpAddress. By preallocating |
|
312 * this handle and never sharing the content, the |
|
313 * Set operation is a simple address copy and no |
|
314 * memory allocation. |
|
315 * |
|
316 * @param aAddr The raw IPv6 address |
|
317 * @param aScopeId The scope id of the address |
|
318 * |
|
319 * @return KErrNone or KErrNoMemory. |
|
320 */ |
|
321 { |
|
322 if (iAddr == NULL || iAddr->IsShared()) |
|
323 { |
|
324 // The End Point does not exist, or is shared in some way. Need to |
|
325 // allocate a new object for this handle. |
|
326 |
|
327 Close(); // Release previous object. |
|
328 iAddr = new CEndPoint(aAddr, aScopeId); |
|
329 if (iAddr == NULL) |
|
330 return KErrNoMemory; |
|
331 } |
|
332 else |
|
333 { |
|
334 if (!iAddr->iList.IsDetached()) |
|
335 { |
|
336 // The object is a member of non-empty collection. However, |
|
337 // because this reference is the only reference to it, |
|
338 // closing would only delete the object. Might as well |
|
339 // just detach it from the collection and reuse the |
|
340 // CEndPoint as is. [this is "just in case" branch -- |
|
341 // the normal intended usage pattern should not make |
|
342 // CEndPoint of this handle to be a member of any |
|
343 // collection!] |
|
344 iAddr->iList.Detach(); |
|
345 } |
|
346 iAddr->iAddr.SetAddress(aAddr, aScopeId); |
|
347 } |
|
348 return KErrNone; |
|
349 } |
|
350 |
|
351 TInt RIpAddress::Set(const TInetAddr &aAddr) |
|
352 /** |
|
353 * Set content to given internet address. |
|
354 * |
|
355 * See the other Set. |
|
356 * |
|
357 * @param aAddr The internet address in IPv6 format. |
|
358 */ |
|
359 { |
|
360 return Set(aAddr.Ip6Address(), aAddr.Scope()); |
|
361 } |
|
362 |
|
363 const TIpAddress& RIpAddress::operator()() const |
|
364 /** |
|
365 * Returns a reference to the contained IP address. |
|
366 * |
|
367 * This reference is only valid as long as handle is open. It must not |
|
368 * be used after the handle is closed. |
|
369 * |
|
370 * Always succeeds, and returns all zeroes address, if handle is not open. |
|
371 * |
|
372 * @return The Address. |
|
373 */ |
|
374 { |
|
375 // This is actually |
|
376 // static const TIpAddress none; |
|
377 // but which cannot be used because TIpAddress has a constructor |
|
378 // and it would result "ipsec6.prt has initialized data" error |
|
379 // for target build. |
|
380 static const char none[sizeof(TIpAddress)] = {0 }; |
|
381 |
|
382 return iAddr ? iAddr->iAddr : reinterpret_cast<const TIpAddress &>(none); |
|
383 } |
|
384 |
|
385 TBool RIpAddress::IsNamed() const |
|
386 { |
|
387 return iAddr ? iAddr->IsNamed() : EFalse; |
|
388 } |
|
389 |
|
390 const TDesC8 &RIpAddress::Name() const |
|
391 { |
|
392 return IsNamed() ? iAddr->Name() : KNullDesC8(); |
|
393 } |
|
394 |
|
395 |
|
396 // |
|
397 // REndPoints implementation // |
|
398 // |
|
399 // |
|
400 // Debug only // |
|
401 // |
|
402 |
|
403 #ifdef _LOG |
|
404 |
|
405 class TAddressBuf : public TBuf<70> |
|
406 { |
|
407 public: |
|
408 TAddressBuf(const TIpAddress &aAddr); |
|
409 }; |
|
410 |
|
411 TAddressBuf::TAddressBuf(const TIpAddress &aAddr) |
|
412 { |
|
413 TInetAddr addr(aAddr, 0); |
|
414 addr.SetScope(aAddr.iScope); |
|
415 addr.OutputWithScope(*this); |
|
416 } |
|
417 |
|
418 void REndPoints::LogPrint(const TDesC &aFormat) const |
|
419 /** |
|
420 * Print the current set of end points into IPSEC Log file. |
|
421 * |
|
422 * The format string must contain exactly two %S format |
|
423 * controls. The first is used for the name and the second |
|
424 * for the currently assigned address. |
|
425 * |
|
426 * @param aFormat The print format. |
|
427 */ |
|
428 { |
|
429 _LIT(KUnnamed, "<internal>"); |
|
430 |
|
431 TCircularListIter iter(*this); |
|
432 RCircularList *r; |
|
433 while ((r = iter++) != NULL) |
|
434 { |
|
435 const CEndPoint &n = CEndPoint::Cast(*r); |
|
436 TAddressBuf addr(n.iAddr); |
|
437 if (n.IsNamed()) |
|
438 { |
|
439 TBuf<100> name; |
|
440 name.Copy(n.Name()); |
|
441 Log::Printf(aFormat, &name, &addr); |
|
442 } |
|
443 else |
|
444 Log::Printf(aFormat, &KUnnamed(), &addr); |
|
445 } |
|
446 } |
|
447 #endif |
|
448 |