|
1 // Copyright (c) 2004-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 // servers.cpp - server manager module |
|
15 // |
|
16 |
|
17 #include "servers.h" |
|
18 #include "engine.h" |
|
19 #include "inet6log.h" |
|
20 #include "dns_hdr.h" // only for KDnsPort! |
|
21 #include "dnd.hrh" |
|
22 |
|
23 // Item of the server list, hold DNS server information |
|
24 class TDnsServerData |
|
25 { |
|
26 public: |
|
27 TInetAddr iAddr; //< DNS Server Address |
|
28 TDnsServerScope iScope; //< The Sever Scope and type (MC/UC) |
|
29 TInt iServerId; //< Id of the server |
|
30 TInt iInterface; //< Index to Interface Array |
|
31 }; |
|
32 |
|
33 // Item of the interface list, hold interface information for DNS |
|
34 class TDnsInterfaceData |
|
35 { |
|
36 public: |
|
37 TName iName; //< Name of the interface |
|
38 TUint32 iScope[16]; //< The scope vector |
|
39 }; |
|
40 |
|
41 // Item of the configured servers list |
|
42 class TDnsConfiguredServer |
|
43 { |
|
44 public: |
|
45 TName iName; |
|
46 TInetAddr iAddr; |
|
47 }; |
|
48 |
|
49 class CDnsServerManager : public CBase, public MDnsServerManager |
|
50 { |
|
51 ~CDnsServerManager(); |
|
52 public: |
|
53 CDnsServerManager(CDndEngine &aControl); |
|
54 void ConstructL(); |
|
55 void ConfigurationChanged(); |
|
56 |
|
57 // |
|
58 // MDnsServerManager API |
|
59 // (for docs, see the MDnsServerManger definitions) |
|
60 // |
|
61 TInt OpenList(const TDnsServerFilter &aFilter, MDnsServerListNotify *aNotify); |
|
62 TInt Count(const TDnsServerFilter &aFilter) const; |
|
63 TInt Next(const TDnsServerFilter &aFilter, TInt aServerId) const; |
|
64 void CloseList(const TDnsServerFilter &aFilter); |
|
65 |
|
66 TInt Address(TInt aServerId, TInetAddr &aAddr) const; |
|
67 TUint32 Scope(TInt aServerId, const TInetAddr &aAddr); |
|
68 TInt ServerId(const TInetAddr &aAddr) const; |
|
69 TUint32 NameSpace(const TDnsServerFilter &aFilter, TInt aServerId) const; |
|
70 TInt BuildServerList(); |
|
71 void AddServerAddress(const TName &aInterface, const TInetAddr &aAddr); |
|
72 void LockByAddress(const TInetAddr &aAddr, TUint32 aNid, TDnsServerFilter &aFilter); |
|
73 |
|
74 private: |
|
75 // Build and add interface entry to the list (basic operation) |
|
76 TInt AddInterfaceEntry(const TSoInetIfQuery &aInfo); |
|
77 // Find interface matching the destination address |
|
78 TInt FindInterface(const TInetAddr &aAddr); |
|
79 // Add new server address to the server list |
|
80 void AddToServerList(const TInetAddr &aAddr, TInt aIf, RSocket &aSocket); |
|
81 // Add new interface to the interface list |
|
82 TInt AddToInterfaceList(const TSoInetInterfaceInfo &aInfo, RSocket &aSocket); |
|
83 // Compare the filter with a DNS server |
|
84 TBool Match(const TDnsServerFilter &aFilter, const TDnsServerData &aServer) const; |
|
85 |
|
86 CDndEngine &iControl; |
|
87 TUint32 iServerId; //< The last used server id. |
|
88 TTime iMark; //< The time of the last configuration change. |
|
89 TUint iConfigure:1; //< Reconfigure needed, if set. |
|
90 TUint iStable:1; //< = 1, when scanned list is supposed to be stable |
|
91 TUint iCacheFlushed:1; //< = 1, when cache has been flushed (only used with "FlushOnConfig" ini-option) |
|
92 |
|
93 CArrayFixFlat<TDnsServerData> *iServerList; //< Current list of servers |
|
94 CArrayFixFlat<TDnsInterfaceData> *iInterfaceList; //< Current list of interfaces |
|
95 CArrayFixFlat<TDnsConfiguredServer> *iConfiguredList; //< Current list of configured servers |
|
96 }; |
|
97 |
|
98 |
|
99 MDnsServerManager *DnsServerManager::NewL(CDndEngine &aControl) |
|
100 { |
|
101 CDnsServerManager *mgr = new (ELeave) CDnsServerManager(aControl); |
|
102 |
|
103 CleanupStack::PushL(mgr); |
|
104 mgr->ConstructL(); |
|
105 CleanupStack::Pop(); |
|
106 return mgr; |
|
107 } |
|
108 |
|
109 // |
|
110 // CDnsServerManager |
|
111 // |
|
112 |
|
113 CDnsServerManager::CDnsServerManager(CDndEngine &aControl) : iControl(aControl) |
|
114 { |
|
115 } |
|
116 |
|
117 void CDnsServerManager::ConstructL() |
|
118 { |
|
119 iServerList = new (ELeave) CArrayFixFlat<TDnsServerData>(2); |
|
120 iInterfaceList = new (ELeave) CArrayFixFlat<TDnsInterfaceData>(5); |
|
121 // iConfiguredList is allocated only if required. |
|
122 } |
|
123 |
|
124 void CDnsServerManager::ConfigurationChanged() |
|
125 { |
|
126 LOG(Log::Printf(_L("CDnsServerManager -- Configuration changed"))); |
|
127 // Just flag that building a new server list is needed. Try |
|
128 // to delay heavy interface scanning operation until really |
|
129 // needed (because configuration changes may come in burts). |
|
130 iConfigure = 1; |
|
131 iStable = 0; |
|
132 iCacheFlushed = 0; |
|
133 iMark.UniversalTime(); |
|
134 } |
|
135 |
|
136 CDnsServerManager::~CDnsServerManager() |
|
137 { |
|
138 delete iServerList; |
|
139 delete iInterfaceList; |
|
140 delete iConfiguredList; |
|
141 } |
|
142 |
|
143 // CDnsServerManager::AddInterfaceData |
|
144 TInt CDnsServerManager::AddInterfaceEntry(const TSoInetIfQuery &aInfo) |
|
145 { |
|
146 TRAPD(err, |
|
147 TDnsInterfaceData &ifd = iInterfaceList->ExtendL(); |
|
148 ifd.iName = aInfo.iName; |
|
149 for (TInt i = sizeof(ifd.iScope) / sizeof(ifd.iScope[0]); --i >= 0; ) |
|
150 ifd.iScope[i] = aInfo.iZone[i]; |
|
151 ); |
|
152 return err < 0 ? err : iInterfaceList->Count() - 1; |
|
153 } |
|
154 |
|
155 // CDnsServerManager::AddToInterfaceList |
|
156 // ************************************* |
|
157 /** |
|
158 // Add the interface to the interface list, if it does not already exist. |
|
159 // The existence is based on comparing the interface names. |
|
160 // |
|
161 // @param aInfo the information that identifies the interface |
|
162 // @param aSocket (must be open) to be used for GetOpt, if needed |
|
163 // @returns |
|
164 // @li < 0, if there are some errors (interface was not added) |
|
165 // @li index to the interface (>= 0) in the interface list. |
|
166 */ |
|
167 TInt CDnsServerManager::AddToInterfaceList(const TSoInetInterfaceInfo &aInfo, RSocket &aSocket) |
|
168 { |
|
169 if (aInfo.iName.Length() == 0) |
|
170 return -1; // Interface must have a name. |
|
171 // |
|
172 // Check if interface already exists and don't insert duplicates |
|
173 // |
|
174 TInt i; |
|
175 for (i = iInterfaceList->Count(); --i >= 0; ) |
|
176 { |
|
177 const TDnsInterfaceData &data = iInterfaceList->At(i); |
|
178 if (data.iName.Compare(aInfo.iName) == 0) |
|
179 return i; // Interface already present in the list |
|
180 } |
|
181 // |
|
182 // A new interface, get the scope vector |
|
183 // |
|
184 TPckgBuf<TSoInetIfQuery> opt; |
|
185 opt().iName = aInfo.iName; |
|
186 const TInt err = aSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt); |
|
187 return err < 0 ? err : AddInterfaceEntry(opt()); |
|
188 } |
|
189 |
|
190 // CDnsServerManager::FindInterface |
|
191 // ******************************** |
|
192 // |
|
193 TInt CDnsServerManager::FindInterface(const TInetAddr &aAddr) |
|
194 { |
|
195 TPckgBuf<TSoInetIfQuery> opt; |
|
196 opt().iDstAddr = aAddr; |
|
197 const TInt err = iControl.iSocket.GetOpt(KSoInetIfQueryByDstAddr, KSolInetIfQuery, opt); |
|
198 if (err < 0) |
|
199 return err; |
|
200 |
|
201 // Check if interface is already known |
|
202 |
|
203 for (TInt i = iInterfaceList->Count(); --i >= 0; ) |
|
204 { |
|
205 const TDnsInterfaceData &data = iInterfaceList->At(i); |
|
206 if (data.iName.Compare(opt().iName) == 0) |
|
207 return i; |
|
208 } |
|
209 // Not present yet, just add it |
|
210 return AddInterfaceEntry(opt()); |
|
211 } |
|
212 |
|
213 // CDnsServerManager::AddToServerList |
|
214 // ********************************** |
|
215 /** |
|
216 // Add new address to the server list. A new entry is only |
|
217 // added if the address does not already exist. |
|
218 // |
|
219 // @param aAddr address of the DNS server |
|
220 // @param aIf the interface (index to the interface list) |
|
221 */ |
|
222 void CDnsServerManager::AddToServerList(const TInetAddr &aAddr, TInt aIf, RSocket &aSocket) |
|
223 { |
|
224 if (aAddr.IsUnspecified()) |
|
225 return; // No address, nothing to add |
|
226 // |
|
227 // Normalize all addresses into IPv6 format |
|
228 // |
|
229 TDnsServerData sd; |
|
230 sd.iAddr = aAddr; |
|
231 sd.iInterface = aIf; |
|
232 if (sd.iAddr.Family() == KAfInet) |
|
233 sd.iAddr.ConvertToV4Mapped(); |
|
234 else if (sd.iAddr.Family() != KAfInet6) |
|
235 return; // Only IPv4 or IPv6 addresses are valid |
|
236 if (sd.iAddr.IsMulticast()) |
|
237 // sd.iScope = (TDnsServerScope)(sd.iAddr.Ip6Address().Scope()); |
|
238 sd.iScope = EDnsServerScope_MC_LOCAL; |
|
239 else |
|
240 sd.iScope = EDnsServerScope_UC_GLOBAL; |
|
241 |
|
242 if (!sd.iAddr.Port()) |
|
243 sd.iAddr.SetPort(KDnsPort); |
|
244 |
|
245 LOG(TBuf<80> dst); |
|
246 LOG(sd.iAddr.OutputWithScope(dst)); |
|
247 LOG(TBuf<80> src); |
|
248 // In typhoon and later, DND never activates interfaces. All |
|
249 // usable server addresses must have a valid route, before |
|
250 // they can be used. Thus, check it... |
|
251 // |
|
252 TPckgBuf<TSoInetIfQuery> opt; |
|
253 opt().iDstAddr = aAddr; |
|
254 const TBool has_route = |
|
255 (aSocket.GetOpt(KSoInetIfQueryByDstAddr, KSolInetIfQuery, opt) == KErrNone) && !opt().iSrcAddr.IsUnspecified(); |
|
256 LOG(opt().iSrcAddr.OutputWithScope(src)); |
|
257 if (!has_route) |
|
258 { |
|
259 LOG(Log::Printf(_L("\t\tnameserver [%S] (src=%S) has no route or no source address, skipped"), &dst, &src)); |
|
260 return; // No route, unusable for now -- ignore |
|
261 } |
|
262 // |
|
263 // Check if address already exists and don't insert duplicates |
|
264 // |
|
265 for (TInt i = iServerList->Count(); --i >= 0; ) |
|
266 { |
|
267 TDnsServerData &a = iServerList->At(i); |
|
268 if (a.iAddr.Match(sd.iAddr) && a.iAddr.Scope() == sd.iAddr.Scope()) |
|
269 { |
|
270 // However, if server didn't have assigned |
|
271 // interface yet, assign it from this call. |
|
272 // |
|
273 if (a.iInterface < 0) |
|
274 a.iInterface = aIf; |
|
275 LOG(Log::Printf(_L("\t\tnameserver (id=%d) [%S] (src=%S)"), a.iServerId, &dst, &src)); |
|
276 return; // Duplicate address, do not add again. |
|
277 } |
|
278 } |
|
279 |
|
280 sd.iServerId = ++iServerId; // Assign a "server id" |
|
281 LOG(Log::Printf(_L("\t\tnameserver (id=%d) [%S] (src=%S) (new)"), sd.iServerId, &dst, &src)); |
|
282 TRAP_IGNORE(iServerList->AppendL(sd)); |
|
283 } |
|
284 |
|
285 // CDnsServerManager::BuildServerList |
|
286 // ********************************** |
|
287 TInt CDnsServerManager::BuildServerList() |
|
288 { |
|
289 LOG(Log::Printf(_L("CDnsServerManager -- Scanning interfaces and building the server list"))); |
|
290 TInt err = KErrNone; |
|
291 |
|
292 // Refresh the current list of DNS server addresses |
|
293 // (this could be skipped if there was some definite way of knowing |
|
294 // that nothing has changed since the last collect...) |
|
295 |
|
296 // Use Delete instead of Reset, so that space is reused? (not freed and reallocated) |
|
297 iInterfaceList->Delete(0, iInterfaceList->Count()); |
|
298 |
|
299 // Trying to keep "server id" stable, thus do not clear existing |
|
300 // server list, but just mark entries, so that unused ones can be |
|
301 // reclaimed after build is complete. |
|
302 for (TInt i = iServerList->Count(); --i >= 0; ) |
|
303 iServerList->At(i).iInterface = -2; |
|
304 |
|
305 LOG(Log::Printf(_L("\t* Scanning interfaces"))); |
|
306 // Read the DNS address from the interface |
|
307 TSoInetInterfaceInfo *info = new TSoInetInterfaceInfo; // allocate large struct from heap! |
|
308 if (info && (err = iControl.iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl)) == KErrNone) |
|
309 { |
|
310 TPckg<TSoInetInterfaceInfo> opt(*info); |
|
311 while (iControl.iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone) |
|
312 { |
|
313 if (opt().iName.Length() == 0) |
|
314 continue; // "null" interface, ignore |
|
315 if (!opt().iAddress.IsUnspecified()) |
|
316 { |
|
317 #ifdef _LOG |
|
318 TBuf<60> tmp; |
|
319 opt().iAddress.OutputWithScope(tmp); |
|
320 Log::Printf(_L("\t%S [%S]"), &opt().iName, &tmp); |
|
321 #endif |
|
322 TInt i = AddToInterfaceList(opt(), iControl.iSocket); |
|
323 AddToServerList((TInetAddr &)(opt().iNameSer1), i, iControl.iSocket); |
|
324 AddToServerList((TInetAddr &)(opt().iNameSer2), i, iControl.iSocket); |
|
325 } |
|
326 else |
|
327 { |
|
328 LOG(Log::Printf(_L("\tInterface: %S [no address, skipping]"), &opt().iName)); |
|
329 } |
|
330 } |
|
331 } |
|
332 delete info; |
|
333 LOG(Log::Printf(_L("\t* Configured interface specific addresses"))); |
|
334 |
|
335 // |
|
336 // Add configured servers, if a matching interface has become available |
|
337 // (assumes that configured list and interface list are always short, so |
|
338 // the loop over all lists is not too bad...) |
|
339 if (iConfiguredList) |
|
340 { |
|
341 for (TInt i = iConfiguredList->Count(); --i >= 0; ) |
|
342 { |
|
343 const TDnsConfiguredServer &cs = iConfiguredList->At(i); |
|
344 for (TInt j = iInterfaceList->Count(); --j >= 0; ) |
|
345 { |
|
346 const TDnsInterfaceData &data = iInterfaceList->At(j); |
|
347 if (data.iName.Compare(cs.iName) == 0) |
|
348 { |
|
349 // Complete the address with the scope id |
|
350 // from the interface! |
|
351 TInetAddr addr(cs.iAddr); |
|
352 if (addr.Family() == KAfInet) |
|
353 addr.ConvertToV4Mapped(); |
|
354 const TUint s = addr.Ip6Address().Scope() - 1; |
|
355 if (s < 16) |
|
356 { |
|
357 addr.SetScope(data.iScope[s]); |
|
358 AddToServerList(addr, j, iControl.iSocket); |
|
359 } |
|
360 break; |
|
361 } |
|
362 } |
|
363 } |
|
364 } |
|
365 // |
|
366 // Remove unused servers from the list |
|
367 // |
|
368 LOG(Log::Printf(_L("\t* Remove stale addresses"))); |
|
369 const TInt N = iServerList->Count(); |
|
370 TInt k = 0; |
|
371 for (TInt j = 0; j < N; ++j) |
|
372 { |
|
373 const TDnsServerData &a = iServerList->At(j); |
|
374 if (a.iInterface != -2) |
|
375 { |
|
376 // This server entry is still used |
|
377 if (k != j) |
|
378 iServerList->At(k) = a; |
|
379 k++; |
|
380 } |
|
381 #ifdef _LOG |
|
382 else |
|
383 { |
|
384 TBuf<80> tmp; |
|
385 a.iAddr.OutputWithScope(tmp); |
|
386 Log::Printf(_L("\t\tnameserver (id=%d) [%S] deleted"), a.iServerId, &tmp); |
|
387 } |
|
388 #endif |
|
389 } |
|
390 if (k < N) |
|
391 { |
|
392 iServerList->Delete(k, N - k); |
|
393 } |
|
394 |
|
395 LOG(Log::Printf(_L("CDnsServerManager -- Done, current server count=%d"), iServerList->Count())); |
|
396 return err; |
|
397 } |
|
398 |
|
399 // CDnsServerManager::AddServerAddress |
|
400 // *********************************** |
|
401 void CDnsServerManager::AddServerAddress(const TName &aInterface, const TInetAddr &aAddr) |
|
402 { |
|
403 if (iConfiguredList == NULL && |
|
404 (iConfiguredList = new CArrayFixFlat<TDnsConfiguredServer>(5)) == NULL) |
|
405 return; // No memory for the allocation, ignore.. |
|
406 |
|
407 // Do not add duplicates, check existing entries |
|
408 for (TInt i = iConfiguredList->Count(); --i >= 0; ) |
|
409 { |
|
410 const TDnsConfiguredServer &cs = iConfiguredList->At(i); |
|
411 if (cs.iName.Compare(aInterface) == 0 && cs.iAddr.Match(aAddr)) |
|
412 return; // Duplicate! |
|
413 } |
|
414 |
|
415 iConfigure = 1; // Request rebuild of server list. |
|
416 |
|
417 TRAP_IGNORE(TDnsConfiguredServer &cf = iConfiguredList->ExtendL(); |
|
418 cf.iAddr = aAddr; |
|
419 cf.iName = aInterface; |
|
420 ); |
|
421 } |
|
422 |
|
423 /** |
|
424 // @param aFilter the server filter |
|
425 // @parma aServer to be tested against the filter |
|
426 // @returns |
|
427 // @li TRUE, if the server matches the filter |
|
428 // @li FALSE, if the server does not match the filter |
|
429 */ |
|
430 TBool CDnsServerManager::Match(const TDnsServerFilter &aFilter, const TDnsServerData &aServer) const |
|
431 { |
|
432 if (aFilter.iServerScope != aServer.iScope) |
|
433 return FALSE; |
|
434 if (aFilter.iLockType < KIp6AddrScopeNodeLocal || aFilter.iLockType > KIp6AddrScopeNetwork) |
|
435 return FALSE; // actually invalid locking scope level |
|
436 |
|
437 // If a server address is specified without interface (-1), then this |
|
438 // server will match any filter (if server scopes are same). |
|
439 if (aServer.iInterface >= 0) |
|
440 { |
|
441 const TDnsInterfaceData &id = iInterfaceList->At(aServer.iInterface); |
|
442 if (aFilter.iLockId != id.iScope[aFilter.iLockType-1]) |
|
443 return FALSE; // Not in locked scope |
|
444 } |
|
445 return TRUE; |
|
446 } |
|
447 |
|
448 |
|
449 // |
|
450 // MDnsServerManager API |
|
451 // |
|
452 TInt CDnsServerManager::OpenList(const TDnsServerFilter &aFilter, MDnsServerListNotify * /*aNotify*/) |
|
453 { |
|
454 if (iConfigure) |
|
455 { |
|
456 const TInt err = BuildServerList(); |
|
457 if (err != KErrNone) |
|
458 return err; |
|
459 iConfigure = 0; |
|
460 } |
|
461 if (iStable) |
|
462 return KErrNone; |
|
463 |
|
464 if (iControl.GetConfig().iFlushOnConfig && iCacheFlushed == 0) |
|
465 { |
|
466 iCacheFlushed = 1; |
|
467 TRAP_IGNORE(iControl.HandleCommandL(EDndFlush)); |
|
468 } |
|
469 |
|
470 TTime stamp; |
|
471 stamp.UniversalTime(); |
|
472 TTimeIntervalSeconds elapsed; |
|
473 stamp.SecondsFrom(iMark, elapsed); |
|
474 if (elapsed.Int() > (TInt)iControl.GetConfig().iSetupTime) |
|
475 { |
|
476 iStable = 1; |
|
477 return KErrNone; |
|
478 } |
|
479 if (aFilter.iServerScope == EDnsServerScope_MC_LOCAL) |
|
480 return KErrNone; |
|
481 // We are still within setup time, return "pending" if no servers available |
|
482 return (Count(aFilter) == 0) ? 1 : KErrNone; |
|
483 } |
|
484 |
|
485 TInt CDnsServerManager::Count(const TDnsServerFilter &aFilter) const |
|
486 { |
|
487 TInt count = 0; |
|
488 for (TInt i = iServerList->Count(); --i >= 0; ) |
|
489 if (Match(aFilter, iServerList->At(i))) |
|
490 ++count; |
|
491 return count; |
|
492 } |
|
493 |
|
494 TInt CDnsServerManager::Next(const TDnsServerFilter &aFilter, TInt aServerId) const |
|
495 { |
|
496 const TInt N = iServerList->Count(); |
|
497 |
|
498 TInt wrap = 0; |
|
499 TInt first_found = 0; |
|
500 TInt current_found = 0; |
|
501 |
|
502 if (aServerId == 0) |
|
503 { |
|
504 // |
|
505 // When "current" server is not specified, Next will |
|
506 // return the first server (specified by iServerId) |
|
507 // |
|
508 for (TInt i = 0; i < N; ++i) |
|
509 { |
|
510 const TDnsServerData &server = iServerList->At(i); |
|
511 if (server.iServerId == aFilter.iServerId) |
|
512 first_found = 1; |
|
513 if (first_found) |
|
514 { |
|
515 if (Match(aFilter, server)) |
|
516 return server.iServerId; |
|
517 } |
|
518 else if (wrap == 0 && Match(aFilter, server)) |
|
519 wrap = server.iServerId; |
|
520 } |
|
521 // |
|
522 // iServerId server is not present (or it and none |
|
523 // of the servers after it do not match). Return |
|
524 // the first matching server. |
|
525 return wrap; |
|
526 } |
|
527 else |
|
528 { |
|
529 // |
|
530 // When aServerId is given, the Next will return |
|
531 // the next matching server between (current, first) |
|
532 // (or fail, if none exists) |
|
533 for (TInt i = 0; i < N; ++i) |
|
534 { |
|
535 const TDnsServerData &server = iServerList->At(i); |
|
536 if (current_found) |
|
537 { |
|
538 if (server.iServerId == aFilter.iServerId) |
|
539 return 0; // Back to first, no Matching server |
|
540 if (Match(aFilter, server)) |
|
541 return server.iServerId; |
|
542 } |
|
543 else |
|
544 { |
|
545 if (server.iServerId == aServerId) |
|
546 // Start looking for the next match |
|
547 current_found = 1; |
|
548 if (server.iServerId == aFilter.iServerId) |
|
549 first_found = 1; |
|
550 if (first_found == 0 && wrap == 0 && Match(aFilter, server)) |
|
551 wrap = server.iServerId; |
|
552 } |
|
553 } |
|
554 // |
|
555 // Wrap around wrapping |
|
556 // |
|
557 if (current_found && first_found) |
|
558 return wrap; |
|
559 } |
|
560 return 0; // No matching next server! |
|
561 } |
|
562 |
|
563 void CDnsServerManager::CloseList(const TDnsServerFilter &/*aFilter*/) |
|
564 { |
|
565 } |
|
566 |
|
567 |
|
568 TInt CDnsServerManager::Address(TInt aServerId, TInetAddr &aAddr) const |
|
569 { |
|
570 const TInt N = iServerList->Count(); |
|
571 for (TInt i = 0; i < N; ++i) |
|
572 { |
|
573 const TDnsServerData &server = iServerList->At(i); |
|
574 if (server.iServerId == aServerId) |
|
575 { |
|
576 aAddr = server.iAddr; |
|
577 return KErrNone; |
|
578 } |
|
579 } |
|
580 return KErrNotFound; |
|
581 } |
|
582 |
|
583 TInt CDnsServerManager::ServerId(const TInetAddr &aAddr) const |
|
584 { |
|
585 for (TInt i = iServerList->Count(); --i >= 0; ) |
|
586 { |
|
587 const TDnsServerData &server = iServerList->At(i); |
|
588 if (server.iAddr.CmpAddr(aAddr) && server.iAddr.Scope() == aAddr.Scope()) |
|
589 return server.iServerId; |
|
590 } |
|
591 return 0; |
|
592 } |
|
593 |
|
594 TUint32 CDnsServerManager::Scope(TInt aServerId, const TInetAddr &aAddr) |
|
595 { |
|
596 const TInt N = iServerList->Count(); |
|
597 for (TInt i = 0; i < N; ++i) |
|
598 { |
|
599 const TDnsServerData &server = iServerList->At(i); |
|
600 if (server.iServerId == aServerId) |
|
601 { |
|
602 const TUint i = aAddr.Ip6Address().Scope() - 1; |
|
603 if (i > 15) |
|
604 return 0; // Bad scope level. |
|
605 const TInt j = server.iInterface < 0 ? FindInterface(server.iAddr) : server.iInterface; |
|
606 if (j >= 0) |
|
607 return (iInterfaceList->At(j)).iScope[i]; |
|
608 } |
|
609 } |
|
610 return 0; |
|
611 } |
|
612 |
|
613 |
|
614 static TUint32 MakeNameSpaceId(TInt aServerScope, const TDnsInterfaceData &aIf) |
|
615 { |
|
616 // |
|
617 // Construct the name space id from the server scope and |
|
618 // matching scope id. |
|
619 // |
|
620 if (aServerScope < 0) |
|
621 aServerScope = -aServerScope; |
|
622 aServerScope -= 1; |
|
623 if (aServerScope >= 0 && aServerScope < 16) |
|
624 return (aIf.iScope[aServerScope] & ~(0xFu << 28)) | ((aServerScope & 0xFu) << 28); |
|
625 return 0; |
|
626 } |
|
627 |
|
628 TUint32 CDnsServerManager::NameSpace(const TDnsServerFilter &aFilter, TInt aServerId) const |
|
629 { |
|
630 if (aFilter.iLockType < KIp6AddrScopeNodeLocal || aFilter.iLockType > KIp6AddrScopeNetwork) |
|
631 return 0; // actually invalid locking type |
|
632 |
|
633 if (aServerId) |
|
634 { |
|
635 const TInt N = iServerList->Count(); |
|
636 for (TInt i = 0; i < N; ++i) |
|
637 { |
|
638 const TDnsServerData &server = iServerList->At(i); |
|
639 if (server.iServerId == aServerId) |
|
640 { |
|
641 if (server.iInterface < 0) |
|
642 break; |
|
643 return MakeNameSpaceId(aFilter.iServerScope, iInterfaceList->At(server.iInterface)); |
|
644 } |
|
645 } |
|
646 // Should this fall to generic search if server is not |
|
647 // found? Or, just return 0? |
|
648 } |
|
649 |
|
650 for (TInt i = iInterfaceList->Count(); --i >= 0; ) |
|
651 { |
|
652 TDnsInterfaceData &id = iInterfaceList->At(i); |
|
653 if (aFilter.iLockId == id.iScope[aFilter.iLockType-1]) |
|
654 return MakeNameSpaceId(aFilter.iServerScope, id); |
|
655 } |
|
656 // Cannot find name space id |
|
657 return 0; |
|
658 } |
|
659 |
|
660 void CDnsServerManager::LockByAddress(const TInetAddr &aAddr, TUint32 aNid, TDnsServerFilter &aFilter) |
|
661 { |
|
662 aFilter.iLockType = aAddr.Ip6Address().Scope(); |
|
663 aFilter.iLockId = aAddr.Scope(); |
|
664 if (aFilter.iLockId) |
|
665 return; // Address specified the scope id, all done. |
|
666 if (aFilter.iLockType == KIp6AddrScopeNetwork) |
|
667 { |
|
668 aFilter.iLockId = aNid; |
|
669 return; // If lock scope level is network, we can use aNid as is. |
|
670 } |
|
671 |
|
672 // Address does not specify the scope id. Try to pick one |
|
673 // from known interfaces based on the network id. |
|
674 for (TInt i = iInterfaceList->Count(); --i >= 0; ) |
|
675 { |
|
676 TDnsInterfaceData &id = iInterfaceList->At(i); |
|
677 if (aNid == id.iScope[KIp6AddrScopeNetwork-1]) |
|
678 { |
|
679 aFilter.iLockId = id.iScope[aFilter.iLockType-1]; |
|
680 break; |
|
681 } |
|
682 } |
|
683 } |