|
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 // Implements the DHCP IP6 highest level control plain |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file DHCPIP6Control.cpp |
|
20 @internalTechnology |
|
21 */ |
|
22 |
|
23 #include "DHCPIP6Control.h" |
|
24 #include "DHCPIP6States.h" |
|
25 #include "DHCPServer.h" |
|
26 #include "DHCPDb.h" |
|
27 #include "NetCfgExtDhcpControl.h" |
|
28 #include "DhcpIP6Msg.h" |
|
29 #include "ExpireTimer.h" |
|
30 #include "DomainNameDecoder.h" |
|
31 #include <comms-infras/es_config.h> |
|
32 #include "netcfgextndhcpmsg.h" |
|
33 #include <nifman.h> |
|
34 #include <f32file.h> |
|
35 #include <comms-infras/metatype.h> |
|
36 #include <comms-infras/metadata.h> |
|
37 #ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
38 #include "dhcphwaddrmanager.h" |
|
39 #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
40 using namespace DHCPv6; |
|
41 |
|
42 struct TDHCPv6Persistent : public Meta::SMetaData |
|
43 { |
|
44 TDHCPv6Persistent( SIdentityAssociationConfigInfoNA& aIdentityAssociationConfigInfoNA ) : |
|
45 iIdentityAssociationConfigInfoNA( &aIdentityAssociationConfigInfoNA ) |
|
46 { |
|
47 iTaskStartedAt.HomeTime(); |
|
48 } |
|
49 TTime iTaskStartedAt; |
|
50 SIdentityAssociationConfigInfoNA* iIdentityAssociationConfigInfoNA; |
|
51 |
|
52 DATA_VTABLE |
|
53 }; |
|
54 |
|
55 START_ATTRIBUTE_TABLE( TDHCPv6Persistent, KDHCPv6Persinstence, KDHCPv6PersinstenceId ) |
|
56 REGISTER_ATTRIBUTE( TDHCPv6Persistent, iIdentityAssociationConfigInfoNA, TMetaObjectPtr<SIdentityAssociationConfigInfoNA> ) |
|
57 REGISTER_ATTRIBUTE( TDHCPv6Persistent, iTaskStartedAt, TMetaTime ) |
|
58 END_ATTRIBUTE_TABLE() |
|
59 |
|
60 |
|
61 CDHCPIP6Control::~CDHCPIP6Control() |
|
62 { |
|
63 } |
|
64 |
|
65 void CDHCPIP6Control::ConfigureL(const TConnectionInfo& aInfo, const RMessage2* aMessage) |
|
66 /** |
|
67 * Open and attach to the RConnection |
|
68 * |
|
69 * @internalTechnology |
|
70 */ |
|
71 { |
|
72 CDHCPControl::ConfigureL( aInfo, aMessage ); |
|
73 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::ConfigureL"))); |
|
74 |
|
75 iDhcpDb = new (ELeave) CDHCPDb( TPtrC( SERVICE_IP6_DNS_ADDR_FROM_SERVER ), |
|
76 TPtrC( SERVICE_IP6_NAME_SERVER1 ), |
|
77 TPtrC( SERVICE_IP6_NAME_SERVER2 )); //for both version for the time being see the class TDHCPIP4Db comments |
|
78 TRAPD( err, FindInterfaceNameL(aInfo,KAfInet6) ); |
|
79 if( err == KErrNone ) |
|
80 { |
|
81 TBuf8<KMaxName> tempBuf; |
|
82 tempBuf.Copy( iInterfaceName ); |
|
83 __CFLOG_1(KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::ConfigureL - FindInterfaceNameL found \"%S\""), &tempBuf); |
|
84 } |
|
85 else |
|
86 { |
|
87 __CFLOG_1(KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::ConfigureL - FindInterfaceNameL failed with error %d"), err); |
|
88 User::Leave( err ); |
|
89 } |
|
90 #ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
91 iDhcpHwAddrManager = CDhcpHwAddrManager::NewL(); |
|
92 iDhcpStateMachine = CDHCPIP6StateMachine::NewL(iEsock, iConnection, iInterfaceName,iDhcpHwAddrManager); |
|
93 #else |
|
94 iDhcpStateMachine = CDHCPIP6StateMachine::NewL(iEsock, iConnection, iInterfaceName); |
|
95 #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
96 |
|
97 CDHCPIP6StateMachine* sm6 = static_cast<CDHCPIP6StateMachine*>(iDhcpStateMachine); |
|
98 TDHCPv6Persistent pers(sm6->iInterfaceConfigInfo.iSIdentityAssociationConfigInfoNA); |
|
99 TBool bStaticAddress = !iDhcpDb->ReadL(*iDhcpStateMachine, pers); |
|
100 //initialise relevant data |
|
101 TInt pos = 0; |
|
102 const SIPAddressInfo* info = pers.iIdentityAssociationConfigInfoNA->GetValidAddressInfo( pos ); |
|
103 TTimeIntervalSeconds seconds = info ? static_cast<TInt>(info->iValidLifeTime) : 0 ; |
|
104 iDhcpDb->iLeaseExpiresAt = pers.iTaskStartedAt + seconds; |
|
105 //the rest of the data we'll get back in reply msg |
|
106 CDHCPControl::ConfigureL(bStaticAddress); |
|
107 } |
|
108 |
|
109 void CDHCPIP6Control::BindingFinishedL() |
|
110 { |
|
111 CDHCPControl::BindingFinishedL(); |
|
112 //see case EDeclineInitialisedInProgress as to how the persistent |
|
113 //data is written |
|
114 } |
|
115 |
|
116 void CDHCPIP6Control::TaskCompleteL(TInt aError) |
|
117 /** |
|
118 * Signals the end of a task |
|
119 * and decides what we should do when |
|
120 * |
|
121 * @internalTechnology |
|
122 */ |
|
123 { |
|
124 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, |
|
125 _L8("CDHCPIP6Control::TaskCompleteL (%d) with error = %d") , |
|
126 iState, aError)); |
|
127 |
|
128 DhcpStateMachine()->Cancel(); |
|
129 TState prevState = iState; |
|
130 switch (iState) |
|
131 { |
|
132 case EDeclineInitialisedInProgress: |
|
133 { |
|
134 TDHCPv6Persistent pers(DhcpStateMachine()->iInterfaceConfigInfo.iSIdentityAssociationConfigInfoNA); |
|
135 //get relevant data from statemachine |
|
136 pers.iTaskStartedAt = DhcpStateMachine()->iStartedAquisitionAt; |
|
137 TRAPD( ret, iDhcpDb->WriteL(*iDhcpStateMachine, pers) ); |
|
138 if (ret!=KErrNone) |
|
139 { |
|
140 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::TaskCompleteL error: %d"),ret)); |
|
141 } |
|
142 iState = EInitialised; |
|
143 break; |
|
144 } |
|
145 case EReconfigureInProgress: |
|
146 //in the case the following fn leave we've run out of memory => we will not respond |
|
147 //to the reconfigure message. However we can still use our address(es) and wait |
|
148 //for renew timer to expire |
|
149 if ( aError == KErrNone ) |
|
150 { |
|
151 CDHCPMessageHeaderIP6* v6Msg = DhcpStateMachine()->DhcpMessage(); |
|
152 COptionNode* pNode = v6Msg->GetOptions().FindOption( EReconfMsg ); |
|
153 if (pNode) |
|
154 { |
|
155 TInt nCode = pNode->GetBigEndian(); |
|
156 switch ( nCode ) |
|
157 { |
|
158 case EReconfigureInformRequest: |
|
159 DhcpStateMachine()->StartInformL( this, EFalse /*static address is either already set or not used*/ ); |
|
160 iState = EInformInProgress; |
|
161 //cancel the renew timer (if any) after succesfully starting the above tasks |
|
162 iTimer->Cancel(); |
|
163 break; |
|
164 case EReconfigureRenew: |
|
165 DhcpStateMachine()->StartRenewL( this,0 ); |
|
166 iState = ERenewInProgress; |
|
167 //cancel the renew timer (if any) after succesfully starting the above tasks |
|
168 iTimer->Cancel(); |
|
169 break; |
|
170 default: |
|
171 // keep restarting reconfigure |
|
172 DhcpStateMachine()->StartReconfigureL( this ); |
|
173 } |
|
174 } |
|
175 else |
|
176 { |
|
177 // keep restarting reconfigure |
|
178 DhcpStateMachine()->StartReconfigureL( this ); |
|
179 } |
|
180 } |
|
181 else |
|
182 { |
|
183 //keep restarting reconfigure until a valid reconfigure arrives or |
|
184 //renew timer expires or interface goes down |
|
185 DhcpStateMachine()->StartReconfigureL( this ); |
|
186 } |
|
187 break; |
|
188 case ERebindInProgress: |
|
189 case EInitInProgress: |
|
190 iTimer->Cancel(); |
|
191 |
|
192 if ( aError != KErrNone ) |
|
193 {//decline all |
|
194 DhcpStateMachine()->iInterfaceConfigInfo.SetAddressStatus( KAddrIndexAll, EMarkForDecline ); |
|
195 } |
|
196 iState = EInitInProgress; //take the same action as for EInitInProgress |
|
197 CDHCPControl::TaskCompleteL(aError); |
|
198 break; |
|
199 case ERenewInProgress: |
|
200 iTimer->Cancel(); |
|
201 if (KErrNone != aError) |
|
202 { |
|
203 //Renew process has failed => start rebind |
|
204 DhcpStateMachine()->StartRebindL( this ); |
|
205 iState = ERebindInProgress; |
|
206 break; |
|
207 } |
|
208 //fall through if no error |
|
209 default: |
|
210 { |
|
211 CDHCPControl::TaskCompleteL(aError); |
|
212 } |
|
213 }; |
|
214 //if the statemachine history indicates CDHCPState::EBinding and aError==KErrNone we have to check whether to |
|
215 //decline any addresses that haven't been verified by the stack as valid ones. If so we initiate decline |
|
216 //to decline the invalid addresses. In case at least one address is valid we go to reconfigure state after the decline. |
|
217 //=> amend UML and doc accordingly. |
|
218 if (DhcpStateMachine()->History() & CDHCPState::EBinding && aError == KErrNone ) |
|
219 {//see CDHCPIP6StateMachine::StartDeclineL |
|
220 DhcpStateMachine()->StartDeclineL( this ); |
|
221 iState = EDeclineInitialisedInProgress; |
|
222 //not changing CDHCPIP6Control state we are initialised and timer is running |
|
223 } |
|
224 else if ( iState == EInitialised || (iState == EEnd && prevState == EInformInProgress)) |
|
225 {//we don't want this to leave |
|
226 #if defined(DHCP_RECONFIGURE_NO_AUTHENTICATION) |
|
227 //we don't support reconfigure until we've sorted out authentication |
|
228 TRAPD(ret, DhcpStateMachine()->StartReconfigureL( this )); |
|
229 if (ret!=KErrNone) |
|
230 { |
|
231 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::TaskCompleteL error: %d"),ret)); |
|
232 } |
|
233 iState = EReconfigureInProgress; |
|
234 #endif |
|
235 } |
|
236 } |
|
237 |
|
238 |
|
239 TInt CDHCPIP6Control::HandleClientRequestL(TUint aName, TInt aValue) |
|
240 { |
|
241 TBool deferAllowed = !iMessage; |
|
242 |
|
243 if (iDhcpStateMachine) |
|
244 { |
|
245 switch (aName) |
|
246 { |
|
247 case KConnAddrRenew: |
|
248 if (deferAllowed && iDhcpStateMachine->IsGettingCfgInfoOnly()) |
|
249 { |
|
250 iTimer->Cancel(); |
|
251 iDhcpStateMachine->Cancel(); |
|
252 iDhcpStateMachine->StartInformL(this,EFalse); |
|
253 iState = EInformInProgress; |
|
254 return ETrue; |
|
255 } |
|
256 break; |
|
257 default: |
|
258 break; |
|
259 } |
|
260 } |
|
261 return CDHCPControl::HandleClientRequestL(aName,aValue); |
|
262 } |
|
263 |
|
264 |
|
265 TInt CDHCPIP6Control::HandleClientRequestL(TUint aName) |
|
266 { |
|
267 return CDHCPIP6Control::HandleClientRequestL(aName,0); |
|
268 } |
|
269 |
|
270 void CDHCPIP6Control::GetRawOptionDataL(TUint aOpCode, TPtr8& aPtr ) |
|
271 { |
|
272 HBufC8* buf = NULL; |
|
273 DHCPv6::CDHCPMessageHeaderIP6 msg(buf); |
|
274 CleanupClosePushL(msg); |
|
275 TPtr8 ptr( const_cast<TUint8*>(iValidMsg.Ptr()), iValidMsg.Length(), iValidMsg.Length() ); |
|
276 msg.iRecord.ParseL(ptr); //no check necessary |
|
277 DHCPv6::COptionNode* pOption = msg.GetOptions().FindOption(aOpCode); |
|
278 if (!pOption) |
|
279 { |
|
280 #ifdef SYMBIAN_TCPIPDHCP_UPDATE |
|
281 // The option is not found try to get the option through DHCP INFORM message |
|
282 //by calling RequestInformOrCompleteCallL |
|
283 CleanupStack::PopAndDestroy(); |
|
284 TUint opcode = aOpCode; |
|
285 TPtr8 optPtr(reinterpret_cast<TUint8*>(&opcode),1,1); |
|
286 return(RequestInformOrCompleteCallL(optPtr)); |
|
287 #else |
|
288 User::Leave(KErrNotFound); |
|
289 #endif //SYMBIAN_TCPIPDHCP_UPDATE |
|
290 } |
|
291 ptr.Set(pOption->GetBodyDes()); |
|
292 if (ptr.Length() > aPtr.MaxLength()) |
|
293 { |
|
294 User::Leave(KErrOverflow); |
|
295 } |
|
296 aPtr.Copy(ptr); |
|
297 CleanupStack::PopAndDestroy(); |
|
298 } |
|
299 |
|
300 /** |
|
301 Get raw option data (IP6 version). |
|
302 @param pointer to the buffer descriptor for getting option data |
|
303 */ |
|
304 void CDHCPIP6Control::HandleGetRawOptionDataL(TDes8* aDes) |
|
305 { |
|
306 TDhcp6RawOptionDataPckg pckg(*aDes); |
|
307 |
|
308 TUint16 opCode = pckg.OpCode(); |
|
309 TPtr8 buf(pckg.Buf()); |
|
310 |
|
311 GetRawOptionDataL(opCode, buf); |
|
312 pckg.SetBufLengthL(buf.Length()); |
|
313 } |
|
314 |
|
315 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
316 void CDHCPIP6Control::GetDhcpHdrSiaddrL(TDes8& /*aNxtAddress*/) |
|
317 { |
|
318 //presently empty implementation. |
|
319 //PREQ 1647& 1648 implmentation is only for IPv4 |
|
320 } |
|
321 |
|
322 void CDHCPIP6Control::GetDhcpHdrSnameL(TDes8& /*aHdrSvrName*/) |
|
323 { |
|
324 //presently empty implementation. |
|
325 //PREQ 1647& 1648 implmentation is only for IPv4 |
|
326 } |
|
327 void CDHCPIP6Control::HandleGetTftpServerNameL(TDes8& /*aDes*/) |
|
328 { |
|
329 //presently empty implementation. |
|
330 //PREQ 1647& 1648 implmentation is only for IPv4 |
|
331 } |
|
332 void CDHCPIP6Control::HandleGetTftpServerAddrL(TDes8& /*aDes*/) |
|
333 { |
|
334 //presently empty implementation. |
|
335 //PREQ 1647& 1648 implmentation is only for IPv4 |
|
336 } |
|
337 #endif |
|
338 #ifdef SYMBIAN_TCPIPDHCP_UPDATE |
|
339 void CDHCPIP6Control::RequestInformOrCompleteCallL(TDes8& aOpcodePtr) |
|
340 /** |
|
341 * The RequestInformOrCompleteCallL function |
|
342 * |
|
343 * Checks DHCPINFORM message should be sent or not |
|
344 * @param aOpcodePtr pointer to the opcode list to be updated in iSavedExtraParameters |
|
345 * @internalTechnology |
|
346 */ |
|
347 { |
|
348 |
|
349 if (!iDhcpStateMachine->iDhcpInformAckPending) |
|
350 { |
|
351 if (!iDhcpStateMachine->iSavedExtraParameters.Length()) |
|
352 { |
|
353 iDhcpStateMachine->iSavedExtraParameters.CreateL(aOpcodePtr); |
|
354 } |
|
355 else |
|
356 { |
|
357 iDhcpStateMachine->iSavedExtraParameters.ReAllocL(iDhcpStateMachine->iSavedExtraParameters.Length()+aOpcodePtr.Length()); |
|
358 iDhcpStateMachine->iSavedExtraParameters.Append(aOpcodePtr); |
|
359 } |
|
360 //Cancel if there is any outstanding request(DHCP reconfigure will cancelled) |
|
361 iDhcpStateMachine->Cancel(); |
|
362 static_cast<CDHCPIP6StateMachine*>(iDhcpStateMachine)->StartInformL( this); |
|
363 iDhcpStateMachine->iDhcpInformAckPending=ETrue; |
|
364 iState = EInformInProgress; |
|
365 } |
|
366 else |
|
367 { |
|
368 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8(" RequestInformOrCompleteCallL::Client tried to fetch a option but none has (yet) been received"))); |
|
369 iDhcpStateMachine->iDhcpInformAckPending=EFalse; |
|
370 User::Leave(KErrNotFound); |
|
371 } |
|
372 } |
|
373 #endif //SYMBIAN_TCPIPDHCP_UPDATE |
|
374 |
|
375 #ifdef SYMBIAN_TCPIPDHCP_UPDATE |
|
376 void CDHCPIP6Control::HandleGetMultipleParamsL(TDes8& aDes) |
|
377 #else |
|
378 void CDHCPIP6Control::HandleGetMultipleParamsL(TDes8& /*aDes */) |
|
379 #endif //SYMBIAN_TCPIPDHCP_UPDATE |
|
380 /** |
|
381 * This function will be called when the application want to retrieve multiple |
|
382 * options from the server by using option ORO(option 6) |
|
383 * |
|
384 * @see RFC 3315 sec 22.7 |
|
385 * @internalTechnology |
|
386 */ |
|
387 { |
|
388 #ifdef SYMBIAN_TCPIPDHCP_UPDATE |
|
389 HBufC8 *saveBuf=NULL, *buffer=NULL; |
|
390 TUint16 *headerPtr; |
|
391 TInt numOfOpcodes=0; |
|
392 TInt totalLength=0,opcodeLength=aDes.Length(); |
|
393 TInt maxLength=aDes.MaxLength(); |
|
394 TUint16 opcode; |
|
395 TBool allFound=ETrue; |
|
396 |
|
397 DHCPv6::CDHCPMessageHeaderIP6 msgSaved(saveBuf); |
|
398 TPtr8 savedPtr(const_cast<TUint8*>(iValidMsg.Ptr()), iValidMsg.Length(), iValidMsg.Length()); |
|
399 CleanupClosePushL(msgSaved); |
|
400 msgSaved.iRecord.ParseL(savedPtr); |
|
401 |
|
402 //The below for loop checks all the required opcode data is present or not |
|
403 //The message opcode data is not present in the iValidMsg buffer,the corresponding |
|
404 //opcodes are stored in iCurrentParameters for sending it in DHCPINFORM message |
|
405 for(TInt i=0;i<opcodeLength;i++) |
|
406 { |
|
407 opcode=*(aDes.Ptr()+i); //search required opcode is present or not, one by one |
|
408 |
|
409 DHCPv6::COptionNode* findNode = msgSaved.GetOptions().FindOption(opcode); |
|
410 if (findNode ) |
|
411 { |
|
412 //get the opcode length |
|
413 TInt bufLength=findNode->GetItemLength(); |
|
414 totalLength+=bufLength; |
|
415 //The opcode buffer length is greater than maximum length through overflow error |
|
416 if ((totalLength+1) > maxLength) |
|
417 { |
|
418 totalLength-=bufLength; |
|
419 continue; //current buffer is too big..so hope next buffer is small |
|
420 } |
|
421 if (!buffer) |
|
422 { |
|
423 buffer=HBufC8::NewLC(totalLength + 1);//+1 is extra byte to store number of opcodes |
|
424 buffer->Des().Append(KNoChar); |
|
425 } |
|
426 else |
|
427 { |
|
428 buffer=buffer->ReAllocL(totalLength + 1); |
|
429 CleanupStack::Pop();//buffer as ptr address has changed |
|
430 CleanupStack::PushL(buffer); |
|
431 } |
|
432 headerPtr = reinterpret_cast<TUint16*>(findNode->Ptr()); |
|
433 ++numOfOpcodes; |
|
434 //Append the opcode information to the buffer |
|
435 buffer->Des().Append(reinterpret_cast<const TUint8*>(headerPtr),bufLength); |
|
436 } |
|
437 else |
|
438 { |
|
439 //If atleast one opcode, among the requested, is not found then request through |
|
440 //DHCP INFORM message by calling RequestInformOrCompleteCallL |
|
441 allFound=EFalse; |
|
442 } |
|
443 } |
|
444 |
|
445 if (allFound ) //everything is present..just return call now itself.. |
|
446 { |
|
447 if ((totalLength + 1) > maxLength || totalLength<=0) |
|
448 { |
|
449 User::Leave(KErrOverflow); |
|
450 } |
|
451 if(buffer) // buffer would be NULL only when aDes.Length = 0 which is a rare scenario. But still check it to avoid NULL pointer dereference. |
|
452 { |
|
453 aDes.Copy(buffer->Ptr(), buffer->Length()); |
|
454 TBuf8<1> dummy; |
|
455 dummy.FillZ(1); |
|
456 dummy[0]=numOfOpcodes; |
|
457 aDes.Replace(0,1,dummy);//update number of opcodes collected |
|
458 } |
|
459 } |
|
460 else |
|
461 { |
|
462 //If the option is not found then trigger the information request |
|
463 TPtr8 opcodePtr(const_cast<TUint8*>(aDes.Ptr()),opcodeLength); |
|
464 opcodePtr.SetLength(opcodeLength); |
|
465 RequestInformOrCompleteCallL(opcodePtr); |
|
466 } |
|
467 |
|
468 if (buffer) |
|
469 { |
|
470 CleanupStack::PopAndDestroy(buffer); |
|
471 } |
|
472 |
|
473 CleanupStack::PopAndDestroy(&msgSaved); |
|
474 #endif //SYMBIAN_TCPIPDHCP_UPDATE |
|
475 } |
|
476 |
|
477 TInt CDHCPIP6Control::InformCompleteRequestHandlerL() |
|
478 /** |
|
479 * The InformCompleteRequestHandlerL function |
|
480 * |
|
481 * The function will be called after the DHCPACK message is received, and |
|
482 * iValidMsg buffer has been updated. |
|
483 * Looks for the requested options present or not and appropriately calls |
|
484 * the function handlers |
|
485 * |
|
486 * @return KErrNone if the required data option is found else corresponding error code. |
|
487 * @internalTechnology |
|
488 */ |
|
489 { |
|
490 #ifdef SYMBIAN_TCPIPDHCP_UPDATE |
|
491 TUint optionName = iMessage->Int1(); |
|
492 TInt length = iMessage->Int3(); |
|
493 |
|
494 HBufC8 *buff=HBufC8::NewMaxLC(length) ; |
|
495 TPtr8 ptr(buff->Des()); |
|
496 iMessage->ReadL(2, ptr); |
|
497 |
|
498 switch(optionName) |
|
499 { |
|
500 case KConnGetDhcpRawOptionData: |
|
501 { |
|
502 HandleGetRawOptionDataL(&ptr); |
|
503 iMessage->WriteL(2,ptr); |
|
504 break; |
|
505 } |
|
506 |
|
507 case KConnDhcpGetMultipleParams : |
|
508 { |
|
509 HandleGetMultipleParamsL(ptr); |
|
510 iMessage->WriteL(2,ptr); |
|
511 break; |
|
512 } |
|
513 |
|
514 default: |
|
515 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("InformCompleteRequestHandlerL : default unhandled optino Name"))); |
|
516 break; |
|
517 |
|
518 } |
|
519 iDhcpStateMachine->iDhcpInformAckPending=EFalse; |
|
520 CleanupStack::PopAndDestroy(buff); |
|
521 return KErrNone; |
|
522 #else |
|
523 return EFalse; |
|
524 #endif //SYMBIAN_TCPIPDHCP_UPDATE |
|
525 } |
|
526 void CDHCPIP6Control::HandleGetSipServerAddrL(TDes8* aDes) |
|
527 { |
|
528 SSipServerAddr* sipServerAddr = |
|
529 reinterpret_cast<SSipServerAddr*>(const_cast<TUint8*>(aDes->Ptr())); |
|
530 |
|
531 HBufC8* buf = NULL; |
|
532 DHCPv6::CDHCPMessageHeaderIP6 msg(buf); |
|
533 CleanupClosePushL(msg); |
|
534 TPtr8 ptr(const_cast<TUint8*>(iValidMsg.Ptr()), iValidMsg.Length(), iValidMsg.Length()); |
|
535 msg.iRecord.ParseL(ptr); |
|
536 |
|
537 DHCPv6::COptionList* optionList = &(msg.GetOptions()); |
|
538 |
|
539 CDHCPOptionSipServerAddrs* sipServerAddrs = |
|
540 static_cast<CDHCPOptionSipServerAddrs*>(optionList->FindOption(ESipServerA)); |
|
541 |
|
542 TBool ret = EFalse; |
|
543 |
|
544 if(sipServerAddrs) |
|
545 { |
|
546 ret = sipServerAddrs->GetSipServerAddr(sipServerAddr->index, |
|
547 sipServerAddr->address); |
|
548 } |
|
549 |
|
550 User::LeaveIfError(ret ? KErrNone : KErrNotFound); |
|
551 CleanupStack::PopAndDestroy(); |
|
552 } |
|
553 |
|
554 void CDHCPIP6Control::HandleGetSipServerDomainL(TDes8* aDes) |
|
555 { |
|
556 SSipServerDomain* sipServerDomain = |
|
557 reinterpret_cast<SSipServerDomain*>(const_cast<TUint8*>(aDes->Ptr())); |
|
558 |
|
559 HBufC8* buf = NULL; |
|
560 DHCPv6::CDHCPMessageHeaderIP6 msg(buf); |
|
561 CleanupClosePushL(msg); |
|
562 TPtr8 ptr(const_cast<TUint8*>(iValidMsg.Ptr()), iValidMsg.Length(), iValidMsg.Length()); |
|
563 msg.iRecord.ParseL(ptr); |
|
564 |
|
565 DHCPv6::COptionList* optionList = &(msg.GetOptions()); |
|
566 |
|
567 CDHCPOptionSipServerDomains* sipServerDomains = |
|
568 static_cast<CDHCPOptionSipServerDomains*>(optionList->FindOption(ESipServerD)); |
|
569 |
|
570 if(sipServerDomains) |
|
571 { |
|
572 CDomainNameCodec* domainNameDecoder = new(ELeave) CDomainNameCodec(); |
|
573 CleanupStack::PushL(domainNameDecoder); |
|
574 TPtr8 ptr = sipServerDomains->GetBodyDes(); |
|
575 domainNameDecoder->DecodeL(ptr); |
|
576 |
|
577 if(sipServerDomain->index < (TInt)domainNameDecoder->NumDomainNames()) |
|
578 { |
|
579 TDomainName domainName = (*domainNameDecoder)[sipServerDomain->index]; |
|
580 sipServerDomain->domainName.Copy(domainName); |
|
581 } |
|
582 else |
|
583 { |
|
584 User::Leave(KErrNotFound); |
|
585 } |
|
586 |
|
587 CleanupStack::PopAndDestroy(); |
|
588 } |
|
589 else |
|
590 { |
|
591 User::Leave(KErrNotFound); |
|
592 } |
|
593 |
|
594 CleanupStack::PopAndDestroy(); |
|
595 } |
|
596 #ifdef SYMBIAN_TCPIPDHCP_UPDATE |
|
597 void CDHCPIP6Control::HandleGetDomainSearchListL(TDes8* aDes) |
|
598 /** |
|
599 * This function will be called when the application want to retrieve the |
|
600 * list of Domain names from the DomainSearchList option (option 24)by using |
|
601 * KConnGetDomainSearchList variable. |
|
602 * |
|
603 * @see RFC 3646, |
|
604 * @internalTechnology |
|
605 */ |
|
606 { |
|
607 SDomainSearchList* domainsearchlist = |
|
608 reinterpret_cast<SDomainSearchList*>(const_cast<TUint8*>(aDes->Ptr())); |
|
609 |
|
610 HBufC8* buf = NULL; |
|
611 DHCPv6::CDHCPMessageHeaderIP6 msg(buf); |
|
612 CleanupClosePushL(msg); |
|
613 TPtr8 ptr(const_cast<TUint8*>(iValidMsg.Ptr()), iValidMsg.Length(), iValidMsg.Length()); |
|
614 msg.iRecord.ParseL(ptr); |
|
615 |
|
616 DHCPv6::COptionList* optionList = &(msg.GetOptions()); |
|
617 |
|
618 CDHCPOptionDomainSearchList* domainsearchlistoption = |
|
619 static_cast<CDHCPOptionDomainSearchList*>(optionList->FindOption(EDomainList)); |
|
620 |
|
621 if(domainsearchlistoption) |
|
622 { |
|
623 if(domainsearchlist->index >= 0) |
|
624 { |
|
625 CDomainNameCodec* domainNameDecoder = new(ELeave) CDomainNameCodec(); |
|
626 CleanupStack::PushL(domainNameDecoder); |
|
627 TPtr8 ptr = domainsearchlistoption->GetBodyDes(); |
|
628 domainNameDecoder->DecodeL(ptr); |
|
629 |
|
630 if(domainsearchlist->index < (TInt)domainNameDecoder->NumDomainNames()) |
|
631 { |
|
632 TDomainName domainName = (*domainNameDecoder)[domainsearchlist->index]; |
|
633 domainsearchlist->domainname.Copy(domainName); |
|
634 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::HandleGetDomainSearchListL -index = %d domain name = \"%S\" "), domainsearchlist->index,&(domainsearchlist->domainname))); |
|
635 } |
|
636 else |
|
637 { |
|
638 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::HandleGetDomainSearchListL: Client tried to fetch an out-of-range domain names %d (I only know about %d)"), domainsearchlist->index , (TInt)domainNameDecoder->NumDomainNames())); |
|
639 User::Leave(KErrNotFound); |
|
640 } |
|
641 |
|
642 CleanupStack::PopAndDestroy(domainNameDecoder); |
|
643 } |
|
644 else |
|
645 { |
|
646 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::HandleGetDomainSearchListL: index is not >=0 %d "), domainsearchlist->index)); |
|
647 User::Leave(KErrNotFound); |
|
648 } |
|
649 } |
|
650 else |
|
651 { |
|
652 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::HandleGetDomainSearchListL option is not found "))); |
|
653 User::Leave(KErrNotFound); |
|
654 } |
|
655 |
|
656 CleanupStack::PopAndDestroy(&msg); |
|
657 } |
|
658 |
|
659 void CDHCPIP6Control::HandleGetDNSServerListL(TDes8* aDes) |
|
660 /** |
|
661 * This function will be called when the application want to retrieve the |
|
662 * list of IPV6 addresses of DNS recursive name server from the |
|
663 * DNS Recursive Name Server option (option 23)by using |
|
664 * KConnGetDNSServerList variable. |
|
665 * |
|
666 * @see RFC 3646, |
|
667 * @internalTechnology |
|
668 */ |
|
669 { |
|
670 SDNSServerAddr* dnsServerAddr = |
|
671 reinterpret_cast<SDNSServerAddr*>(const_cast<TUint8*>(aDes->Ptr())); |
|
672 |
|
673 HBufC8* buf = NULL; |
|
674 DHCPv6::CDHCPMessageHeaderIP6 msg(buf); |
|
675 CleanupClosePushL(msg); |
|
676 TPtr8 ptr(const_cast<TUint8*>(iValidMsg.Ptr()), iValidMsg.Length(), iValidMsg.Length()); |
|
677 msg.iRecord.ParseL(ptr); |
|
678 |
|
679 DHCPv6::COptionList* optionList = &(msg.GetOptions()); |
|
680 |
|
681 CDHCPOptionDNSServers* dnsServerAddrsoption = |
|
682 static_cast<CDHCPOptionDNSServers*>(optionList->FindOption(EDNSServers)); |
|
683 |
|
684 TInt ret = KErrNone; |
|
685 if(dnsServerAddrsoption) |
|
686 { |
|
687 if(dnsServerAddr->index >=0) |
|
688 { |
|
689 ret = dnsServerAddrsoption->GetDomainNameServer(dnsServerAddr->index, |
|
690 dnsServerAddr->addres); |
|
691 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::HandleGetDNSServerListL -index = %d DNS server address = \"%S\" "), ret,&(dnsServerAddr->addres))); |
|
692 } |
|
693 else |
|
694 { |
|
695 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::HandleGetDNSServerListL -index is out of range "))); |
|
696 ret = KErrNotFound; |
|
697 } |
|
698 } |
|
699 else |
|
700 { |
|
701 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPIP6Control::HandleGetDNSServerListL option is not found "))); |
|
702 ret = KErrNotFound; |
|
703 } |
|
704 |
|
705 User::LeaveIfError(ret); |
|
706 CleanupStack::PopAndDestroy(&msg); |
|
707 |
|
708 } |
|
709 #endif //SYMBIAN_TCPIPDHCP_UPDATE |