|
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 // llmnrnotifyhandler.cpp - Link-local multicast name resolution |
|
15 // notify handler |
|
16 // CDndLlmnrNotifyHandler |
|
17 // |
|
18 |
|
19 #ifdef LLMNR_ENABLED |
|
20 |
|
21 #if defined(TCPIP6_USE_COMMDB) |
|
22 # include <commdb.h> |
|
23 #else |
|
24 # include <commsdattypesv1_1.h> |
|
25 # include <commsdattypesv1_1_partner.h> |
|
26 using namespace CommsDat; |
|
27 #endif |
|
28 |
|
29 #include "engine.h" |
|
30 #include "llmnrresponder.h" |
|
31 #include "inet6log.h" |
|
32 |
|
33 CDndLlmnrNotifyHandler::CDndLlmnrNotifyHandler(CDndLlmnrResponder &aMaster) |
|
34 : iTimeout(CLlmnrNotifyHandlerTimeoutLinkage::Timeout), iMaster(aMaster) |
|
35 { |
|
36 } |
|
37 |
|
38 CDndLlmnrNotifyHandler::~CDndLlmnrNotifyHandler() |
|
39 { |
|
40 iTimeout.Cancel(); |
|
41 } |
|
42 |
|
43 void CDndLlmnrNotifyHandler::ConstructL() |
|
44 { |
|
45 LOG(Log::Printf(_L("CDndLlmnrNotifyHandler::ConstructL() size=%d\r\n"), (TInt)sizeof(*this))); |
|
46 } |
|
47 |
|
48 void CDndLlmnrNotifyHandler::ConfigurationChanged() |
|
49 { |
|
50 iMaster.iControl.Timer().Set(iTimeout, iMaster.iLlmnrConf->iNotifyTime); |
|
51 } |
|
52 |
|
53 void CDndLlmnrNotifyHandler::ScanInterfaces() |
|
54 { |
|
55 (void)iMaster.iControl.CheckResult |
|
56 (_L("Setting Socket options"), |
|
57 iMaster.iControl.iSocket.SetOpt(KSoInetEnumInterfaces, |
|
58 KSolInetIfCtrl)); |
|
59 |
|
60 TSoInetInterfaceInfo *info = new TSoInetInterfaceInfo; // allocate large struct from heap! |
|
61 if (info == NULL) |
|
62 return; // No memory! |
|
63 TPckg<TSoInetInterfaceInfo> opt(*info); |
|
64 |
|
65 TPckgBuf<TSoInetIfQuery> opt2; |
|
66 opt2().iName.SetLength(0); |
|
67 |
|
68 TUint32 iap_id = 0; // Current IAP ID (== iZone[1]) |
|
69 TInt llmnr_disabled = 0; // (init just to silence warning! this value is never used). |
|
70 |
|
71 iMaster.UpdateStart(); |
|
72 while(iMaster.iControl.iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone) |
|
73 { |
|
74 // Check address configured |
|
75 if(opt().iAddress.IsUnspecified()) |
|
76 continue; // No address, ignore |
|
77 // KSoInetNextInterface returns an entry for each configured |
|
78 // address. Skip entry, if previous entry was the same real |
|
79 // interface. [This is only optimization that lessens the |
|
80 // generated log messages--not for speed]. |
|
81 if (opt().iName.Compare(opt2().iName) == 0) |
|
82 continue; |
|
83 opt2().iName = opt().iName; |
|
84 TInt err = iMaster.iControl.iSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, opt2); |
|
85 if(err != KErrNone) |
|
86 { |
|
87 LOG(Log::Printf(_L("CDndLlmnrNotifyHandler::ScanInterfaces GetOpt KSoInetIfQueryByName error: %d"),err)); |
|
88 } |
|
89 else |
|
90 { |
|
91 LOG(Log::Printf(_L("CDndLlmnrNotifyHandler::ScanInterfaces - Interface up, name: %S\r\n"), &opt().iName)); |
|
92 |
|
93 if (iap_id != opt2().iZone[1]) |
|
94 { |
|
95 // Different IAP, need to find whether LLMNR is to be enabled or disabled |
|
96 iap_id = opt2().iZone[1]; |
|
97 TRAPD(err, llmnr_disabled = IsLlmnrDisabledL(iap_id)); |
|
98 if (err != KErrNone) |
|
99 llmnr_disabled = 1; // By default (if no configuration present), disable it. |
|
100 } |
|
101 TIpVer ipver; |
|
102 if(opt().iAddress.Family() == KAfInet || opt().iAddress.IsV4Mapped()) |
|
103 ipver = EIPv4; |
|
104 else |
|
105 ipver = EIPv6; |
|
106 iMaster.UpdateInterface(opt2().iName, ipver, opt2().iZone, opt().iHwAddr, llmnr_disabled); |
|
107 } |
|
108 } |
|
109 delete info; |
|
110 iMaster.UpdateFinish(); |
|
111 } |
|
112 |
|
113 void CDndLlmnrNotifyHandler::Timeout(const TTime &) |
|
114 { |
|
115 LOG(Log::Printf(_L("--> CDndLlmnrNotifyHandler::Timeout() -start-"))); |
|
116 ScanInterfaces(); |
|
117 LOG(Log::Printf(_L("<-- CDndLlmnrNotifyHandler::Timeout() -exit-"))); |
|
118 } |
|
119 |
|
120 |
|
121 |
|
122 /** |
|
123 * Acquire LLMNR configuration flag for the IAP from the CommDB. |
|
124 * |
|
125 * @return |
|
126 * @li 0, if configuration not found or LLMNR is enabled by the configuration |
|
127 * @li 1, if LLMNR is disabled by the configuration. |
|
128 * |
|
129 * Leave is implicit disable. |
|
130 */ |
|
131 TInt CDndLlmnrNotifyHandler::IsLlmnrDisabledL(TUint32 aIap) |
|
132 { |
|
133 TBool enable = 1; // If CommsDB does not have SERVICE_ENABLE_LLMNR, the default is enabled! |
|
134 #if defined(TCPIP6_USE_COMMDB) |
|
135 # ifdef SERVICE_ENABLE_LLMNR |
|
136 CCommsDatabase* db = CCommsDatabase::NewL(); |
|
137 CleanupStack::PushL(db); // cleanup 1 |
|
138 |
|
139 CCommsDbTableView* iap = db->OpenViewMatchingUintLC(TPtrC(IAP), TPtrC(COMMDB_ID), aIap); // cleanup 2 |
|
140 User::LeaveIfError(iap->GotoFirstRecord()); |
|
141 TBuf<KCommsDbSvrMaxFieldLength> service_type; |
|
142 TUint32 service; |
|
143 iap->ReadTextL(TPtrC(IAP_SERVICE_TYPE), service_type); |
|
144 iap->ReadUintL(TPtrC(IAP_SERVICE), service); |
|
145 CCommsDbTableView *srv = db->OpenViewMatchingUintLC(service_type, TPtrC(COMMDB_ID), service); // cleanup 3 |
|
146 User::LeaveIfError(srv->GotoFirstRecord()); |
|
147 srv->ReadBoolL(TPtrC(SERVICE_ENABLE_LLMNR), enable); |
|
148 CleanupStack::PopAndDestroy(3); |
|
149 # else |
|
150 (void)aIap; |
|
151 # endif |
|
152 #else |
|
153 #ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY |
|
154 CMDBSession *dB = CMDBSession::NewLC(KCDVersion1_2); |
|
155 #else |
|
156 CMDBSession *dB = CMDBSession::NewLC(KCDVersion1_1); |
|
157 #endif |
|
158 |
|
159 |
|
160 // Reveal hidden or private IAP records if a licensee has chosen to protect a record |
|
161 // using one of these flags - the API to do this is public so internal components |
|
162 // have to support the use of such records. |
|
163 dB->SetAttributeMask( ECDHidden | ECDPrivate ); |
|
164 |
|
165 CCDIAPRecord* iap = static_cast<CCDIAPRecord *>(CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord)); |
|
166 CleanupStack::PushL(iap); |
|
167 iap->SetRecordId(aIap); |
|
168 LOG(Log::Printf(_L("IsLlmnrDisabledL: LoadL for IAP=%d"), aIap)); |
|
169 iap->LoadL(*dB); |
|
170 LOG(Log::Printf(_L("IsLlmnrDisabledL: LoadL OK, doing LoadL for service"))); |
|
171 #if 0 |
|
172 iap->iService.LoadL(*dB); |
|
173 #else |
|
174 const TDesC& servType = iap->iServiceType; |
|
175 |
|
176 if (servType.CompareF(TPtrC(KCDTypeNameDialOutISP))==0) |
|
177 { |
|
178 iap->iService.iLinkedRecord = static_cast<CCDDialOutISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialOutISPRecord)); |
|
179 } |
|
180 else if (servType.CompareF(TPtrC(KCDTypeNameDialInISP))==0) |
|
181 { |
|
182 iap->iService.iLinkedRecord = static_cast<CCDDialInISPRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDialInISPRecord)); |
|
183 } |
|
184 else if (servType.CompareF(TPtrC(KCDTypeNameLANService))==0) |
|
185 { |
|
186 iap->iService.iLinkedRecord = static_cast<CCDLANServiceRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdLANServiceRecord)); |
|
187 } |
|
188 else if (servType.CompareF(TPtrC(KCDTypeNameWLANServiceExt))==0) |
|
189 { |
|
190 iap->iService.iLinkedRecord = static_cast<CCDWLANServiceExtRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdWLANServiceExtRecord)); |
|
191 } |
|
192 else if (servType.CompareF(TPtrC(KCDTypeNameVPNService))==0) |
|
193 { |
|
194 iap->iService.iLinkedRecord = static_cast<CCDVPNServiceRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdVPNServiceRecord)); |
|
195 } |
|
196 else if (servType.CompareF(TPtrC(KCDTypeNameVPNService))==0) |
|
197 { |
|
198 iap->iService.iLinkedRecord = static_cast<CCDVPNServiceRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdVPNServiceRecord)); |
|
199 } |
|
200 else if (servType.CompareF(TPtrC(KCDTypeNameOutgoingWCDMA))==0) |
|
201 { |
|
202 iap->iService.iLinkedRecord = static_cast<CCDOutgoingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdOutgoingGprsRecord)); |
|
203 } |
|
204 else if (servType.CompareF(TPtrC(KCDTypeNameIncomingWCDMA))==0) |
|
205 { |
|
206 iap->iService.iLinkedRecord = static_cast<CCDIncomingGprsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdIncomingGprsRecord)); |
|
207 } |
|
208 else if (servType.CompareF(TPtrC(KCDTypeNameDefaultWCDMA))==0) |
|
209 { |
|
210 iap->iService.iLinkedRecord = static_cast<CCDDefaultWCDMARecord*>(CCDRecordBase::RecordFactoryL(KCDTIdDefaultWCDMARecord)); |
|
211 } |
|
212 else |
|
213 { |
|
214 LOG(Log::Printf(_L("CDndLlmnrNotifyHandler::IsLlmnrDisabledL() service type not supported (%S)\r\n"), &servType)); |
|
215 goto fail; |
|
216 } |
|
217 iap->iService.iLinkedRecord->SetRecordId(iap->iService); |
|
218 iap->iService.iLinkedRecord->LoadL(*dB); |
|
219 #endif |
|
220 fail: |
|
221 CCDServiceRecordBase *const ptrService = static_cast<CCDServiceRecordBase *>(iap->iService.iLinkedRecord); |
|
222 LOG(Log::Printf(_L("IsLlmnrDisabledL: LoadL for service returns=[%u]"), (TInt)ptrService)); |
|
223 if (ptrService) |
|
224 enable = ptrService->iServiceEnableLlmnr; |
|
225 else |
|
226 enable = 0; |
|
227 CleanupStack::PopAndDestroy(2); |
|
228 #endif |
|
229 LOG(Log::Printf(_L("IsLlmnrDisabledL: enable=%d"), enable)); |
|
230 return enable == 0; |
|
231 } |
|
232 |
|
233 |
|
234 #endif |