|
1 // Copyright (c) 2003-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 control plain |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file DHCPControl.cpp |
|
20 @internalTechnology |
|
21 */ |
|
22 |
|
23 #include "DHCPControl.h" |
|
24 #include "DHCPStates.h" |
|
25 #include "DHCPStateMachine.h" |
|
26 #include "DHCPConfigListener.h" |
|
27 #include "DNSUpdateIf.h" |
|
28 #include "DHCPDb.h" |
|
29 #include "DHCPMsg.h" |
|
30 #include "NetCfgExtDhcpControl.h" |
|
31 #include <nifman.h> |
|
32 #include <comms-infras/es_config.h> |
|
33 #ifdef _DEBUG |
|
34 #include "DHCPServer.h" |
|
35 #endif |
|
36 |
|
37 #include "DHCPStatesDebug.h" |
|
38 |
|
39 #ifdef SYMBIAN_NETWORKING_PLATSEC |
|
40 #include <comms-infras/rconfigdaemonmess.h> |
|
41 #else |
|
42 #include <comms-infras\cs_daemonmess.h> |
|
43 #endif |
|
44 |
|
45 #ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
46 #include "dhcphwaddrmanager.h" |
|
47 const TInt KEightBit = 8; |
|
48 #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
49 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
50 #include <nifman_internal.h> |
|
51 #endif |
|
52 |
|
53 |
|
54 CDHCPControl::~CDHCPControl() |
|
55 { |
|
56 CompleteClientMessage( KErrCancel ); // complete all. must be before the rest to avoid deadlock with ESOCK |
|
57 delete iDhcpStateMachine; |
|
58 delete iTimer; |
|
59 iConnection.Close(); |
|
60 delete iDhcpDb; |
|
61 iValidMsg.Close(); |
|
62 delete iDhcpConfigListener; |
|
63 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
64 delete iDNSRawOption; |
|
65 #ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
66 delete iDhcpHwAddrManager; |
|
67 #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
68 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
69 } |
|
70 |
|
71 //_LIT(KIp6Interface1,"ipcp6"); |
|
72 //_LIT(KIp6Interface2,"eth6"); |
|
73 |
|
74 void CDHCPControl::FindInterfaceNameL(const TConnectionInfo& aInfo, TInt aFamily) |
|
75 /** |
|
76 * Finds the interface name by querying |
|
77 * the connection for the name |
|
78 * |
|
79 * @internalTechnology |
|
80 */ |
|
81 { |
|
82 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::FindInterfaceName"))); |
|
83 |
|
84 TConnectionInfoBuf connInfo = aInfo; |
|
85 // store IAP for later so we can access CommDB |
|
86 iDhcpDb->iIapId = connInfo().iIapId; |
|
87 User::LeaveIfError(iConnection.Open(iEsock)); |
|
88 User::LeaveIfError(iConnection.Attach(connInfo, RConnection::EAttachTypeMonitor)); |
|
89 TInt err = KErrNotFound; // to ensure we can check that we found connection info |
|
90 |
|
91 TPckgBuf<TConnInterfaceName> name; |
|
92 name().iIndex=1; |
|
93 //this is somethig unheard of in OO environment that we cannot get hold of a simple object relations |
|
94 //forced to do this horrible stuff |
|
95 RSocket socket; |
|
96 User::LeaveIfError(socket.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp,iConnection)); |
|
97 // make socket invisible for interface counting |
|
98 User::LeaveIfError(socket.SetOpt(KSoKeepInterfaceUp, KSolInetIp, 0)); |
|
99 |
|
100 CleanupClosePushL( socket ); |
|
101 TPckgBuf<TSoInet6InterfaceInfo> info; |
|
102 while ( err == KErrNotFound && iConnection.Control(KCOLProvider, KConnGetInterfaceName, name) == KErrNone ) |
|
103 { |
|
104 TSoInet6InterfaceInfo& q = info(); |
|
105 User::LeaveIfError(socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl, 0)); |
|
106 do |
|
107 { |
|
108 User::LeaveIfError(socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, info)); |
|
109 } |
|
110 while ( q.iName != name().iName ); |
|
111 |
|
112 if ( q.iState == EIfUp && |
|
113 q.iAddress.Family() == KAfInet6 && !q.iAddress.IsV4Mapped() ) |
|
114 { |
|
115 if ( (TUint)aFamily == KAfInet6 ) |
|
116 { |
|
117 err = KErrNone; |
|
118 } |
|
119 } |
|
120 else if ( (TUint)aFamily == KAfInet ) |
|
121 { |
|
122 err = KErrNone; |
|
123 } |
|
124 #if 0 |
|
125 switch (aFamily) |
|
126 { |
|
127 case KAfInet6: |
|
128 if ( name().iName.FindF( KIp6Interface1 ) != KErrNotFound || |
|
129 name().iName.FindF( KIp6Interface2 ) != KErrNotFound ) |
|
130 { |
|
131 err = KErrNone; |
|
132 } |
|
133 break; |
|
134 case KAfInet: |
|
135 if ( name().iName.FindF( KIp6Interface1 ) == KErrNotFound && |
|
136 name().iName.FindF( KIp6Interface2 ) == KErrNotFound ) |
|
137 { |
|
138 err = KErrNone; |
|
139 } |
|
140 break; |
|
141 }; |
|
142 #endif |
|
143 name().iIndex++; |
|
144 } |
|
145 User::LeaveIfError(err); // make sure we found something useful |
|
146 CleanupStack::PopAndDestroy( 1 ); //socket |
|
147 iInterfaceName = name().iName; |
|
148 } |
|
149 |
|
150 void CDHCPControl::Cancel() |
|
151 { |
|
152 CompleteClientMessage( KErrCancel ); //cancel all. must be before the rest to avoid deadlock with ESOCK |
|
153 if(iDhcpStateMachine) |
|
154 { |
|
155 iDhcpStateMachine->Cancel(); |
|
156 } |
|
157 |
|
158 iInitStartedByRenew = EFalse; |
|
159 } |
|
160 |
|
161 TBool CDHCPControl::CompleteClientMessage(TInt aError, TInt aFunctionToCancel) |
|
162 /** |
|
163 * If necessary then complete client. |
|
164 * If complete is performed, true is returned |
|
165 */ |
|
166 { |
|
167 if (iMessage && |
|
168 !iMessage->IsNull() && |
|
169 ( aFunctionToCancel == -1 || aFunctionToCancel == iMessage->Function() || EConfigDaemonDeregister == iMessage->Function() ) ) |
|
170 { |
|
171 iMessage->Complete(aError); |
|
172 iMessage = NULL; |
|
173 return ETrue; |
|
174 } |
|
175 return EFalse; |
|
176 } |
|
177 |
|
178 |
|
179 |
|
180 void CDHCPControl::BindingFinishedL() |
|
181 { |
|
182 //cancel any pending timer |
|
183 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::BindingFinishedL"))); |
|
184 iTimer->Cancel(); |
|
185 UpdateDns(iDhcpStateMachine->iHostName, iDhcpStateMachine->iDomainName); |
|
186 iDhcpStateMachine->iStartedAquisitionAt.HomeTime(); //remember acquisition time |
|
187 |
|
188 /** A compromise til we have implemented the "lifetime" option (#42) for |
|
189 * stateless configuration mode - if iRenewalTimeT1 hasn't been read (because we |
|
190 * didn't read IA information), we don't attempt a renew later. |
|
191 * This prevents entry to the renew functionality which acts as though we are |
|
192 * in stateful mode (attempting a full renew / rebind / re-lease) |
|
193 */ |
|
194 if(iDhcpStateMachine->iRenewalTimeT1) |
|
195 { |
|
196 //Start renewal timer |
|
197 iTimer->After(static_cast<TTimeIntervalSeconds>(iDhcpStateMachine->iRenewalTimeT1), *this); |
|
198 } |
|
199 SaveMessageBufferForLaterReference(); |
|
200 ServiceAnyOutstandingIoctlL(); |
|
201 CompleteClientConfigureMessage(KErrNone); |
|
202 DHCP_DEBUG_PUBLISH_READY(DHCPDebug::EReady); |
|
203 } |
|
204 |
|
205 |
|
206 void CDHCPControl::ServiceAnyOutstandingIoctlL() |
|
207 { |
|
208 if(iMessage && !iMessage->IsNull() && (iMessage->Function() == EConfigDaemonIoctl || iMessage->Function() == EConfigDaemonDeregister)) |
|
209 { |
|
210 TInt err = KErrNone; |
|
211 |
|
212 // Run the request again, this time service it (because iMessage is set). We need |
|
213 // to check to make sure the IOCTL is not a renew which has caused a reinitialisation |
|
214 // - we don't want to restart the IOCTL!. |
|
215 if( ( ( iState != EInitInProgress ) && ( iState != EInformInProgress ) ) || !iInitStartedByRenew ) |
|
216 { |
|
217 TRAP(err,HandleClientRequestL(*iMessage)); |
|
218 } |
|
219 iInitStartedByRenew = EFalse; |
|
220 |
|
221 CompleteClientIoctlMessage(err); |
|
222 } |
|
223 } |
|
224 |
|
225 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
226 void CDHCPControl::ServiceAnyOutstandingServerIoctlL() |
|
227 { |
|
228 if(iMessage && !iMessage->IsNull() && iMessage->Function() == EConfigDaemonIoctl) |
|
229 { |
|
230 // run the request again, this time service it (because iMessage is set) |
|
231 TRAPD(err,HandleClientRequestL(*iMessage)); |
|
232 CompleteServerIoctlMessage(err); |
|
233 } |
|
234 } |
|
235 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
236 |
|
237 void CDHCPControl::SaveMessageBufferForLaterReference() |
|
238 { |
|
239 //save the msg buffer in case user wants to retrieve any info |
|
240 TPtr8 messageBuf = iDhcpStateMachine->Message()->Message().Des(); |
|
241 TInt len = messageBuf.Length(); |
|
242 TInt err = KErrNone; |
|
243 |
|
244 if ( iValidMsg.MaxLength() < len ) |
|
245 { |
|
246 //we cannot use any other buffer (e.g ~CMessageSender one) unfortunately since the |
|
247 //message options are valid over potential renew/rebind initalised manualy, by |
|
248 //timeout or reconfigure. |
|
249 iValidMsg.Close(); |
|
250 err = iValidMsg.Create(len); |
|
251 } |
|
252 //if we cannot create the iValidMsg then, well, bad luck |
|
253 if ( err == KErrNone ) |
|
254 { |
|
255 iValidMsg.Copy(messageBuf); |
|
256 } |
|
257 else |
|
258 { |
|
259 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::SaveMessageBufferForLaterReference Error %d: couldn't store received message"),err)); |
|
260 } |
|
261 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
262 if (iDhcpStateMachine->iDhcpInformAckPending && iMessage) |
|
263 { |
|
264 TRAPD(err,InformCompleteRequestHandlerL()); |
|
265 CompleteClientIoctlMessage(err); |
|
266 iDhcpStateMachine->iDhcpInformAckPending=EFalse; |
|
267 } |
|
268 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
269 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
270 if(iDHCPServerImpl) |
|
271 { |
|
272 if(iDNSRawOption) |
|
273 { |
|
274 TPtr8 ptr = iDNSRawOption->Des(); |
|
275 HandleSetRawOptionCodeL(&ptr); |
|
276 } |
|
277 } |
|
278 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
279 } |
|
280 |
|
281 |
|
282 TBool CDHCPControl::OnCompletion( CStateMachine* aStateMachine ) |
|
283 /** |
|
284 * OnCompletion function |
|
285 * |
|
286 * if this method returns ETrue then aStateMachine deletes itself. |
|
287 * In this case it does not ever return ETrue. |
|
288 * Called upon completion or when suspended. |
|
289 * |
|
290 * @see CStateMachine::iSuspendRequest comment |
|
291 * @internalTechnology |
|
292 */ |
|
293 { |
|
294 TRAPD(err, TaskCompleteL(aStateMachine->LastError())); |
|
295 if (err != KErrNone) |
|
296 { |
|
297 // complete the client if this release was prompted by them |
|
298 if(CompleteClientConfigureMessage(err)) |
|
299 { |
|
300 // i.e. only if client is waiting for a configure action (not ioctl) |
|
301 |
|
302 if(err != KErrNoMemory ) |
|
303 { |
|
304 // by doing this we will make sockets get errored as there is no src addr |
|
305 iDhcpStateMachine->RemoveConfiguredAddress(); |
|
306 iValidMsg.Close(); |
|
307 } |
|
308 } |
|
309 } |
|
310 return EFalse; //Always!!! |
|
311 } |
|
312 |
|
313 void CDHCPControl::SaveAndHandleClientRequestL(const RMessage2& aMessage,TUint aOptionName,TInt aValue ) |
|
314 { |
|
315 TInt deferRequest=0; |
|
316 |
|
317 deferRequest = CDHCPControl::HandleClientRequestL(aOptionName,aValue); |
|
318 |
|
319 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::SaveAndHandleClientRequestL"))); |
|
320 |
|
321 iMessage = &aMessage; |
|
322 if( !deferRequest ) |
|
323 { |
|
324 CompleteClientIoctlMessage(KErrNone); |
|
325 } |
|
326 else |
|
327 { |
|
328 if (deferRequest < KErrNone ) |
|
329 { |
|
330 //return the err Value and complete immediately |
|
331 CompleteClientIoctlMessage(deferRequest); |
|
332 } |
|
333 } |
|
334 } |
|
335 |
|
336 |
|
337 void CDHCPControl::HandleClientRequestL(const RMessage2& aMessage) |
|
338 /** |
|
339 * Receives client requests from RConnection. |
|
340 * |
|
341 * This is the base implementation that is called |
|
342 * to service client requests. It handles the |
|
343 * reading and writing of data into the message |
|
344 * and passes control to the derived implementation |
|
345 * to provide the correct info, then completes the message |
|
346 * when done. If there is an error the message |
|
347 * is completed by the session. |
|
348 * |
|
349 * DEFERRING: |
|
350 * |
|
351 * When the request is first made, and it's possible to defer the request. |
|
352 * This is done by setting iMessage to the message. |
|
353 * |
|
354 * @internalTechnology |
|
355 */ |
|
356 { |
|
357 if (aMessage.Function() == EConfigDaemonDeregister) |
|
358 { |
|
359 iDhcpDaemonDeregister = ETrue; |
|
360 SaveAndHandleClientRequestL(aMessage,KConnAddrRelease); |
|
361 return; |
|
362 } |
|
363 |
|
364 if(aMessage.Function() != EConfigDaemonIoctl || |
|
365 iMessage != 0 && iMessage != &aMessage) |
|
366 { |
|
367 User::Leave(KErrUnknown); |
|
368 } |
|
369 |
|
370 TUint optionName = aMessage.Int1(); |
|
371 TInt length = aMessage.Int3(); |
|
372 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
373 TInt desLength= aMessage.GetDesLength(2); |
|
374 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
375 |
|
376 #if _DEBUG |
|
377 if(optionName & KDhcpInterfaceDbgIoctl) |
|
378 { |
|
379 HandleInterfaceDebugL(aMessage); |
|
380 } |
|
381 else |
|
382 #endif |
|
383 if (length>0) |
|
384 { |
|
385 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
386 //Only below commands are supported by DHCP server implementation. |
|
387 //Any other commands are not supported. |
|
388 if(iDHCPServerImpl) |
|
389 { |
|
390 #ifndef SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
391 if(optionName != KConnSetDhcpRawOptionData ) |
|
392 #else |
|
393 if((optionName != KConnSetDhcpRawOptionData ) && (optionName != KConnDhcpSetHwAddressParams)) |
|
394 #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
395 { |
|
396 CompleteClientIoctlMessage(KErrNotSupported); |
|
397 } |
|
398 } |
|
399 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
400 |
|
401 if(optionName == KConnAddrRenew) |
|
402 { |
|
403 //processing renew with user defined timeout |
|
404 |
|
405 TInt secValue; |
|
406 TPckg<TInt> val(secValue); |
|
407 aMessage.ReadL(2, val,0); |
|
408 |
|
409 SaveAndHandleClientRequestL(aMessage, optionName,secValue); |
|
410 } |
|
411 else |
|
412 { |
|
413 HBufC8* buffer = HBufC8::NewMaxLC(length); |
|
414 TPtr8 ptr = buffer->Des(); |
|
415 aMessage.ReadL(2, ptr); |
|
416 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
417 ptr.SetLength(desLength); |
|
418 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
419 |
|
420 TInt deferRequest = HandleClientRequestL(optionName, &ptr); |
|
421 |
|
422 iMessage = &aMessage; |
|
423 if( !deferRequest ) |
|
424 { |
|
425 // request was serviced.. complete immediately |
|
426 aMessage.WriteL(2, ptr); |
|
427 CompleteClientIoctlMessage(KErrNone); |
|
428 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
429 iDhcpStateMachine->iDhcpInformAckPending=EFalse; |
|
430 #endif//SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
431 } |
|
432 else |
|
433 { |
|
434 if (deferRequest < KErrNone) |
|
435 { |
|
436 //return the err Value and complete immediately |
|
437 CompleteClientIoctlMessage(deferRequest); |
|
438 } |
|
439 } |
|
440 CleanupStack::PopAndDestroy(buffer); |
|
441 } |
|
442 } |
|
443 else |
|
444 { |
|
445 SaveAndHandleClientRequestL(aMessage,optionName); |
|
446 } |
|
447 } |
|
448 |
|
449 void CDHCPControl::HandleInterfaceDebugL(const RMessage2& aMessage) |
|
450 /** |
|
451 * Receives client requests for Debug on this interface. |
|
452 * |
|
453 * @internalTechnology |
|
454 */ |
|
455 { |
|
456 #ifdef _DEBUG |
|
457 //-- perform debug control from the client side. |
|
458 //-- Enabled for debug builds only. |
|
459 TUint optionName = aMessage.Int1(); |
|
460 TInt length = aMessage.Int3(); |
|
461 TInt nResult = KErrNone; |
|
462 |
|
463 if(optionName & KDhcpInterfaceDbgIoctl) |
|
464 { |
|
465 |
|
466 TPckgBuf<TInt> ctlParamBuf; |
|
467 TInt ctlParam = 0; |
|
468 |
|
469 //-- read IOCTL parameter if appropriate |
|
470 if(optionName & KConnReadUserDataBit) |
|
471 { |
|
472 //-- the parameter should be TUint as it is a debug control parameter |
|
473 if(length != static_cast<TInt>(sizeof(TUint))) |
|
474 { |
|
475 nResult = KErrArgument; //-- wrong parameter type |
|
476 } |
|
477 else |
|
478 { |
|
479 aMessage.ReadL(2, ctlParamBuf); |
|
480 ctlParam = ctlParamBuf(); |
|
481 } |
|
482 } |
|
483 |
|
484 if(nResult == KErrNone) |
|
485 { |
|
486 //-- perform IOCTL functon |
|
487 switch(optionName) |
|
488 { |
|
489 case KDHCP_GetPubSubMonitorHandle: |
|
490 |
|
491 //-- easy handle.. state machine pointer. |
|
492 ctlParam = (TInt)iDhcpStateMachine; |
|
493 |
|
494 nResult = KErrNone; |
|
495 break; |
|
496 |
|
497 default: |
|
498 nResult = KErrArgument; //-- wrong function |
|
499 }//switch |
|
500 |
|
501 //-- write IOCTL result if appropriate |
|
502 if(optionName & KConnWriteUserDataBit) |
|
503 { |
|
504 ctlParamBuf() = ctlParam; |
|
505 aMessage.WriteL(2,ctlParamBuf); |
|
506 } |
|
507 |
|
508 } |
|
509 |
|
510 aMessage.Complete(nResult); |
|
511 } |
|
512 #else |
|
513 aMessage.Complete(KErrNotSupported); |
|
514 #endif |
|
515 } |
|
516 |
|
517 |
|
518 |
|
519 void CDHCPControl::ConfigureL(const TConnectionInfo& /*aInfo*/, const RMessage2* aMessage) |
|
520 /** |
|
521 * Open and attach to the RConnection |
|
522 * |
|
523 * @internalTechnology |
|
524 */ |
|
525 { |
|
526 // This ConfigureL is called at the start of the derived class ConfigureL. |
|
527 |
|
528 iMessage = aMessage; |
|
529 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::ConfigureL"))); |
|
530 |
|
531 delete iDhcpStateMachine; |
|
532 iDhcpStateMachine = NULL; |
|
533 delete iDhcpDb; |
|
534 iDhcpDb = NULL; |
|
535 |
|
536 delete iTimer; |
|
537 iTimer = NULL; |
|
538 iTimer = CExpireTimer::NewL(); |
|
539 } |
|
540 |
|
541 void CDHCPControl::ConfigureL( TBool aStaticAddress ) |
|
542 { |
|
543 // This ConfigureL is called at the end of the derived class ConfigureL. |
|
544 // We create the listener here as by now the interface name should be set. |
|
545 // Also, this is before the state m/c is started so we are already |
|
546 // registered for linklocal events. |
|
547 if (!iDhcpConfigListener) |
|
548 { |
|
549 // we will continue normal processing if we fail on construction in any way |
|
550 TRAP_IGNORE(iDhcpConfigListener = CDHCPConfigListener::NewL(iInterfaceName, *this)); |
|
551 } |
|
552 |
|
553 // if we have ipAddrFromServer = EFalse in commDB then we have read the static address |
|
554 // and must therefore inform of static ipaddress to the dhcp server. The ReadCommDbL |
|
555 // returns the value of the ipAddrFromServer field |
|
556 //iConfigType = EConfigNoIPAddress; |
|
557 if ((aStaticAddress) || iConfigType == EConfigNoIPAddress) |
|
558 { |
|
559 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
560 if(iDHCPServerImpl) |
|
561 { |
|
562 iDhcpStateMachine->iSvrState = ESvrBinding; |
|
563 CompleteClientConfigureMessage(KErrNone); |
|
564 } |
|
565 else |
|
566 { |
|
567 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
568 // We must find out if any information critical to connection start completion is not yet known.. |
|
569 if(InformNegotiationIsRequiredForConnectionStartCompletion()) |
|
570 { |
|
571 // .. if that's the case we must try to find it by DHCP before we complete the connection start. |
|
572 iDhcpStateMachine->StartInformL(this,aStaticAddress); |
|
573 iState = EInformInProgress; |
|
574 } |
|
575 else |
|
576 { |
|
577 // .. otherwise we can defer negotiations til a client specifically needs to access an option |
|
578 // (e.g. SIP server address) |
|
579 iState = EDeferredInform; |
|
580 CompleteClientConfigureMessage(KErrNone); |
|
581 } |
|
582 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
583 } |
|
584 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
585 } |
|
586 else |
|
587 { |
|
588 TTime timeNow; |
|
589 timeNow.HomeTime(); |
|
590 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("Lease expires at: %Ld. Time now: %Ld"),iDhcpDb->iLeaseExpiresAt.Int64(),timeNow.Int64())); |
|
591 if (iDhcpDb->iLeaseExpiresAt>timeNow) |
|
592 { |
|
593 #ifdef _DEBUG |
|
594 if (CDHCPServer::DebugFlags() & KDHCP_ForceDiscovery) |
|
595 { |
|
596 iDhcpStateMachine->StartInitL(this, iConfigType == EConfigIPAddress ? CDHCPStateMachine::ESubsequentCalls : CDHCPStateMachine::EFirstCall); |
|
597 iState = EInitInProgress; |
|
598 } |
|
599 else |
|
600 { |
|
601 iDhcpStateMachine->StartRebootL(this); |
|
602 iState = EInitInProgress; |
|
603 } |
|
604 #else |
|
605 iDhcpStateMachine->StartRebootL(this); |
|
606 iState = EInitInProgress; |
|
607 #endif |
|
608 } |
|
609 else |
|
610 { |
|
611 // lease has already expired or we didn't have one... |
|
612 // so we must do discovery but can request the known ip address if there is one... |
|
613 iDhcpStateMachine->StartInitL(this, iConfigType == EConfigIPAddress ? CDHCPStateMachine::ESubsequentCalls : CDHCPStateMachine::EFirstCall); |
|
614 iState = EInitInProgress; |
|
615 } |
|
616 } |
|
617 |
|
618 DHCP_DEBUG_PUBLISH_READY(DHCPDebug::ENotReady); |
|
619 } |
|
620 |
|
621 |
|
622 TBool CDHCPControl::InformNegotiationIsRequiredForConnectionStartCompletion(void) const |
|
623 { |
|
624 // We assume that we already know that we don't need to use DHCP to find an ip address |
|
625 // This is reasonable as this method shouldn't be called from a discover/request control path. |
|
626 |
|
627 // Check if it's DHCP's job to find DNS addresses.. |
|
628 if(iDhcpStateMachine->iNameServerAddressesFromServer && |
|
629 ! iDhcpStateMachine->DoesInterfaceKnowAnyDNSServers() ) |
|
630 { |
|
631 iDhcpStateMachine->SetFastTimeoutDuringInform(); |
|
632 return ETrue; |
|
633 } |
|
634 |
|
635 return EFalse; |
|
636 } |
|
637 |
|
638 TBool CDHCPControl::ShouldInformAfterFailedInit(void) |
|
639 { |
|
640 return EFalse; |
|
641 } |
|
642 |
|
643 void CDHCPControl::TimerExpired() |
|
644 /** |
|
645 * Called by the timer to signal that the timer has expired |
|
646 * |
|
647 * @internalTechnology |
|
648 */ |
|
649 { |
|
650 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::TimerExpired()"))); |
|
651 |
|
652 switch (iState) |
|
653 { |
|
654 case EInitialised: |
|
655 case EReconfigureInProgress://this enum should really be changed in derived class |
|
656 //to EInitialised in case |
|
657 //!iDhcpStateMachine->IsGettingCfgInfoOnly() so we could assert but.... |
|
658 //This is renew timeout. Start renew process and rebind timeout. |
|
659 { |
|
660 |
|
661 iDhcpStateMachine->Cancel(); |
|
662 iDhcpStateMachine->iMaxRetryCount = 3; |
|
663 TRAPD(err, iDhcpStateMachine->StartRenewL(this,0)); //If server doesn't respond after 3 attempts, a rebind is initiated..Pls not Ipv6 calculates its own retry values |
|
664 if (err != KErrNone) |
|
665 { |
|
666 //This might happen only due to lack of memory. Retry after timeout. |
|
667 iTimer->After(TTimeIntervalSeconds(KFailTimeOut), *this); |
|
668 return; |
|
669 } |
|
670 iState = ERenewInProgress; |
|
671 iTimer->After(TTimeIntervalSeconds(iDhcpStateMachine->iRebindTimeT2 - iDhcpStateMachine->iRenewalTimeT1 + 1), *this); |
|
672 break; |
|
673 } |
|
674 case ERenewInProgress: |
|
675 //This is rebind timeout. Start rebind process and final lease timeout. |
|
676 { |
|
677 iDhcpStateMachine->Cancel(); |
|
678 TRAPD(err, iDhcpStateMachine->StartRebindL(this)); //If server doesn't respond after 3 attempts, dhcp moves on to the INIT state..Pls not Ipv6 calculates its own retry values |
|
679 if (err != KErrNone) |
|
680 { |
|
681 //This might happen only due to lack of memory. Retry after timeout. |
|
682 iTimer->After(TTimeIntervalSeconds(KFailTimeOut), *this); |
|
683 return; |
|
684 } |
|
685 //Rebind timeout |
|
686 iTimer->After(TTimeIntervalSeconds(iDhcpStateMachine->iLeaseTime - iDhcpStateMachine->iRebindTimeT2 + 1), *this); |
|
687 iState = ERebindInProgress; |
|
688 iDhcpStateMachine->iTaskStartedAt = 0; |
|
689 break; |
|
690 } |
|
691 case ERebindInProgress: |
|
692 //This is lease timeout. |
|
693 //Remove configured address (from TCPIP6 stack) and start discovery process. |
|
694 { |
|
695 iDhcpStateMachine->RemoveConfiguredAddress(); |
|
696 iDhcpStateMachine->Cancel(); |
|
697 iValidMsg.Close(); |
|
698 iDhcpStateMachine->iMaxRetryCount = 2; |
|
699 TRAPD(err, iDhcpStateMachine->StartInitL(this,CDHCPStateMachine::ESubsequentCalls)); |
|
700 if (err != KErrNone) |
|
701 { |
|
702 //This might happen only due to lack of memory. Retry after timeout. |
|
703 iTimer->After(TTimeIntervalSeconds(KFailTimeOut), *this); |
|
704 return; |
|
705 } |
|
706 iState = EInitInProgress; |
|
707 break; |
|
708 } |
|
709 default: |
|
710 _LIT(KDhcpPanicReason, "Timer expired in unexpected state"); |
|
711 User::Panic(KDhcpPanicReason, KErrNotSupported); |
|
712 } |
|
713 } |
|
714 |
|
715 void CDHCPControl::TaskCompleteL(TInt aError) |
|
716 /** |
|
717 * Signals the end of a task |
|
718 * and decides what we should do when |
|
719 * |
|
720 * @internalTechnology |
|
721 */ |
|
722 { |
|
723 // cancel possibly working message sender & socket activity and delete current states |
|
724 iDhcpStateMachine->Cancel(); |
|
725 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, |
|
726 _L8("CDHCPControl::TaskCompleteL (%d) with error = %d") , |
|
727 iState, aError)); |
|
728 if ( aError == KErrServerTerminated ) |
|
729 { |
|
730 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, |
|
731 _L8("CDHCPControl::TaskCompleteL server terminated => complete client request & going to idle"))); |
|
732 iState = EEnd; |
|
733 CompleteClientConfigureMessage(aError); |
|
734 CompleteClientIoctlMessage(aError); |
|
735 return; |
|
736 } |
|
737 switch (iState) |
|
738 { |
|
739 case EInitInProgress: |
|
740 if (KErrTimedOut == aError) |
|
741 { |
|
742 // Listen for Link Local address. |
|
743 // DHCP server is timed out so we unblock our client. |
|
744 if (iDhcpConfigListener && iDhcpConfigListener->HaveLinkLocal()) |
|
745 { |
|
746 CompleteClientConfigureMessage(KErrNone); |
|
747 // don't complete any outstanding ioctl yet.. |
|
748 } |
|
749 } |
|
750 |
|
751 if (iDhcpStateMachine->Idle()) |
|
752 { |
|
753 ServiceAnyOutstandingIoctlL(); |
|
754 CompleteClientConfigureMessage(KErrNone); |
|
755 iState = EEnd; |
|
756 return; |
|
757 } |
|
758 |
|
759 if (iDhcpStateMachine->CompleteClientRequest()) // 'O' flag true in RA |
|
760 { |
|
761 CompleteClientConfigureMessage(KErrNone); |
|
762 iDhcpStateMachine->SetCompleteClientRequestFalse(); |
|
763 iDhcpStateMachine->StartInformL(this, EFalse); |
|
764 return; |
|
765 } |
|
766 |
|
767 if (KErrNone != aError) |
|
768 { |
|
769 iDhcpStateMachine->SetLastError(aError); |
|
770 if (iDhcpStateMachine->History() & CDHCPState::EBinding) |
|
771 { |
|
772 // ARP failed, duplicate address found so cannot use assigned one. Send DHCPDECLINE. |
|
773 // After decline task being finished, we will complete client request with error. |
|
774 iDhcpStateMachine->iMaxRetryCount = 3; |
|
775 iDhcpStateMachine->StartDeclineL(this); |
|
776 iState = EDeclineInProgress; |
|
777 |
|
778 return; |
|
779 } |
|
780 //We received either NACK or not any DHCP server replied. Retry it. |
|
781 if(ShouldInformAfterFailedInit()) |
|
782 { |
|
783 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, |
|
784 _L8("CDHCPControl::TaskCompleteL starting Inform because Init failed..."))); |
|
785 iDhcpStateMachine->StartInformL(this, /*aStaticAddress=*/ ETrue); |
|
786 iState = EInformInProgress; |
|
787 } |
|
788 else |
|
789 { |
|
790 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, |
|
791 _L8("CDHCPControl::TaskCompleteL restarting Init because Init failed..."))); |
|
792 iDhcpStateMachine->iMaxRetryCount = 2; |
|
793 iDhcpStateMachine->StartInitL(this,CDHCPStateMachine::ESubsequentCalls); |
|
794 } |
|
795 |
|
796 return; |
|
797 } |
|
798 |
|
799 // we're bound |
|
800 BindingFinishedL(); |
|
801 iState = EInitialised; |
|
802 break; |
|
803 |
|
804 case ERenewInProgress: |
|
805 if (KErrNone != aError) |
|
806 { |
|
807 //Complete client request with error if there is any |
|
808 CompleteClientConfigureMessage(aError); //unlikely |
|
809 CompleteClientIoctlMessage(aError); |
|
810 //Renew process has failed. |
|
811 return; |
|
812 } |
|
813 |
|
814 // we're bound |
|
815 BindingFinishedL(); |
|
816 iState = EInitialised; |
|
817 break; |
|
818 |
|
819 case ERebindInProgress: |
|
820 if (KErrNone != aError) |
|
821 { |
|
822 //Complete client request with error if there is any |
|
823 CompleteClientConfigureMessage(aError); //unlikely |
|
824 CompleteClientIoctlMessage(aError); |
|
825 //Renew process has failed. We wait for rebind timer (which is already running) |
|
826 //to expire to start rebind process. |
|
827 return; |
|
828 } |
|
829 |
|
830 // we're bound |
|
831 iTimer->Cancel(); |
|
832 BindingFinishedL(); |
|
833 iState = EInitialised; |
|
834 break; |
|
835 |
|
836 case EDeclineInProgress: |
|
837 //Decline message has been sent. Retry discovery. |
|
838 CompleteClientConfigureMessage(aError); |
|
839 iDhcpStateMachine->StartInitL(this,CDHCPStateMachine::ESubsequentCalls); |
|
840 iState = EInitInProgress; |
|
841 break; |
|
842 |
|
843 case EReleaseInProgress: |
|
844 if (! iDhcpDaemonDeregister) |
|
845 { |
|
846 iDhcpStateMachine->RemoveConfiguredAddress(); |
|
847 iDhcpDaemonDeregister = EFalse; |
|
848 } |
|
849 ServiceAnyOutstandingIoctlL(); |
|
850 CompleteClientConfigureMessage(KErrNone); |
|
851 iState = EEnd; |
|
852 break; |
|
853 case EInformInProgress: |
|
854 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
855 if ( aError == KErrTimedOut && iDhcpStateMachine->iDhcpInformAckPending) |
|
856 { |
|
857 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, |
|
858 _L8("CDHCPControl::Inforrm Request TaskCompleteL requests timed out => complete client request & going to idle"))); |
|
859 iState = EEnd; |
|
860 TRAPD(err,InformCompleteRequestHandlerL()); |
|
861 CompleteClientIoctlMessage(err); |
|
862 CompleteClientConfigureMessage(err); |
|
863 return; |
|
864 } |
|
865 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
866 SaveMessageBufferForLaterReference(); |
|
867 ServiceAnyOutstandingIoctlL(); |
|
868 CompleteClientConfigureMessage(KErrNone); |
|
869 DHCP_DEBUG_PUBLISH_READY(DHCPDebug::EReady); |
|
870 iState = EEnd; |
|
871 break; |
|
872 default: |
|
873 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::TaskCompleteL not supported state %d"),iState)); |
|
874 User::Leave(KErrNotSupported); |
|
875 } |
|
876 |
|
877 } |
|
878 |
|
879 TInt CDHCPControl::HandleClientRequestL(TUint aName, TDes8* aDes) |
|
880 /** |
|
881 * Handles client requests made through RConnection. |
|
882 * |
|
883 * Clients can obtain the ip address, |
|
884 * the dhcp server ip address, the remaining lease time |
|
885 * and also renewing and releasing the lease. Any data from |
|
886 * any option can also be returned as raw data using the GetDhcpRawOptionData |
|
887 * request. |
|
888 * |
|
889 * returns True if request could not be serviced immediately (so should be |
|
890 * deferred then serviced later) |
|
891 * |
|
892 * @internalTechnology |
|
893 */ |
|
894 { |
|
895 TTime time; |
|
896 time.HomeTime(); |
|
897 TTimeIntervalSeconds secs; |
|
898 |
|
899 // currently all below options should block client til DHCP negotiation has finished. |
|
900 // We'll service them properly after that. |
|
901 // |
|
902 // when requests are needed which return immediately, more complex logic will be required |
|
903 // to decide whether to block client or service immediately. |
|
904 // |
|
905 // This is only here because it's a decision that should be made here rather than in the calling function |
|
906 // |
|
907 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::HandleClientRequestL state: %d"),iState)); |
|
908 if ( !iMessage && iValidMsg.Length()==0 && iState == EDeferredInform ) |
|
909 { |
|
910 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::HandleClientRequestL -> deferred inform now triggering..."))); |
|
911 iDhcpStateMachine->StartInformL(this, /*aStaticAddress=*/ ETrue); |
|
912 iState = EInformInProgress; |
|
913 |
|
914 return ETrue; |
|
915 } |
|
916 |
|
917 if ( !iMessage && iValidMsg.Length()==0 && iState == EInitInProgress ) |
|
918 { |
|
919 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::HandleClientRequestL EInitInProgress..."))); |
|
920 |
|
921 return ETrue; |
|
922 } |
|
923 |
|
924 // We're not ready to service any of the following ioctls if for some reason we |
|
925 // haven't stored the reply from DHCP (e.g. because we timed out waiting for INFORM response) |
|
926 // |
|
927 // This is more appropriate than letting the sub-handlers throw something less meaningful |
|
928 // |
|
929 if (iValidMsg.Length() == 0) |
|
930 { |
|
931 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
932 if(!iDHCPServerImpl) |
|
933 { |
|
934 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
935 User::Leave(KErrNotReady); |
|
936 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
937 } |
|
938 else |
|
939 { |
|
940 #ifndef SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
941 if(aName != KConnSetDhcpRawOptionData && aName != KConnGetDhcpRawOptionData) |
|
942 #else |
|
943 if(aName != KConnSetDhcpRawOptionData && aName != KConnGetDhcpRawOptionData && aName != KConnDhcpSetHwAddressParams) |
|
944 #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
945 { |
|
946 User::Leave(KErrNotReady); |
|
947 } |
|
948 } |
|
949 |
|
950 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
951 } |
|
952 |
|
953 if (iDhcpStateMachine) |
|
954 { |
|
955 switch (aName) |
|
956 { |
|
957 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
958 case KConnSetDhcpRawOptionData: |
|
959 { |
|
960 HandleSetRawOptionCodeL(aDes); |
|
961 } |
|
962 break; |
|
963 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
964 case KConnGetCurrentAddr: |
|
965 { |
|
966 if (aDes->Length() < static_cast<TInt>(sizeof(TConnectionAddress))) |
|
967 { |
|
968 User::Leave(KErrArgument); |
|
969 } |
|
970 TConnectionAddress* ptr = (TConnectionAddress*)aDes->Ptr(); |
|
971 |
|
972 |
|
973 TInetAddr* addrPtr = new (&(ptr->iAddr))TInetAddr(iDhcpStateMachine->iCurrentAddress); |
|
974 // ptr->iAddr is just some memory in aDes. There is no guarantee that it will be a |
|
975 // valid TInetAddr (or even a valid TDes) so what we do here is just run a constructor |
|
976 // on this already valid memory block and we are now guaranteed to have a valid |
|
977 // TInetAddr - NO MEMORY IS ACTUALLY ALLOCATED BY NEW HERE - see base code for more |
|
978 // details |
|
979 |
|
980 break; |
|
981 } |
|
982 case KConnGetServerAddr: |
|
983 { |
|
984 if (aDes->Length() < static_cast<TInt>(sizeof(TConnectionAddress))) |
|
985 { |
|
986 User::Leave(KErrArgument); |
|
987 } |
|
988 TConnectionAddress* ptr = (TConnectionAddress*)aDes->Ptr(); |
|
989 TInetAddr* addrPtr = new(&(ptr->iAddr))TInetAddr; |
|
990 // ptr->iAddr is just some memory in aDes. There is nno guarantee that it will be a |
|
991 // valid TInetAddr (or even a valid TDes) so what we do here is just run a constructor |
|
992 // on this already valid memory block and we are now guaranteed to have a valid |
|
993 // TInetAddr - NO MEMORY IS ACTUALLY ALLOCATED BY NEW HERE - see base code for more |
|
994 // details |
|
995 |
|
996 iDhcpStateMachine->GetServerAddress( *addrPtr ); |
|
997 break; |
|
998 } |
|
999 case KConnGetAddrLeaseTimeRemain: |
|
1000 { |
|
1001 if (!iDhcpStateMachine->IsGettingCfgInfoOnly()) |
|
1002 { |
|
1003 time.SecondsFrom(iDhcpStateMachine->iStartedAquisitionAt, secs); |
|
1004 |
|
1005 if (aDes->Length()!=static_cast<TInt>(sizeof(TConnectionLeaseInfo))) |
|
1006 { |
|
1007 User::Leave(KErrArgument); |
|
1008 } |
|
1009 (*(TConnectionLeaseInfo*)aDes->Ptr()).iSecondsRemaining = iDhcpStateMachine->iLeaseTime-secs.Int(); |
|
1010 } |
|
1011 break; |
|
1012 } |
|
1013 case KConnGetDhcpRawOptionData: |
|
1014 //-- DHCP option data format is absolutely different for ip4 and ip6 versions. |
|
1015 //-- so, handle this request separately in CDHCPIP4Control and CDHCPIP6Control |
|
1016 HandleGetRawOptionDataL(aDes); |
|
1017 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
1018 if (iDhcpStateMachine->iDhcpInformAckPending) |
|
1019 { |
|
1020 return ETrue; |
|
1021 } |
|
1022 #endif//SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
1023 |
|
1024 break; |
|
1025 |
|
1026 // SIP server/gateway ?? Which? |
|
1027 case KConnGetSipServerAddr: |
|
1028 /* |
|
1029 Different methods of obtaining the SIP server addresses |
|
1030 are specified for IPv4 vs. IPv6. |
|
1031 |
|
1032 RFC3361 - Dynamic Host Configuration Protocol (DHCP-for-IPv4) |
|
1033 Option for Session Initiation Protocol (SIP) Servers |
|
1034 ! - Not currently implemented |
|
1035 |
|
1036 RFC3319 - Dynamic Host Configuration Protocol (DHCPv6) Options |
|
1037 for Session Initiation Protocol (SIP) Servers |
|
1038 */ |
|
1039 |
|
1040 HandleGetSipServerAddrL(aDes); |
|
1041 |
|
1042 break; |
|
1043 |
|
1044 case KConnGetSipServerDomain: |
|
1045 |
|
1046 HandleGetSipServerDomainL(aDes); |
|
1047 break; |
|
1048 #ifdef SYMBIAN_TCPIPDHCP_UPDATE |
|
1049 case KConnGetDomainSearchList: |
|
1050 /* |
|
1051 Extract the list of domain names during name resolution |
|
1052 Refer : RFC3646 - Dynamic Host Configuration Protocol (DHCPv6) Options |
|
1053 for Domain Search List option(option 24) |
|
1054 */ |
|
1055 HandleGetDomainSearchListL(aDes); |
|
1056 break; |
|
1057 |
|
1058 case KConnGetDNSServerList: |
|
1059 /* |
|
1060 Extract the list of IPv6 address of DNS recursive name server |
|
1061 Refer : RFC3646 - DNS Recursive Name Server option(option code 23) |
|
1062 */ |
|
1063 HandleGetDNSServerListL(aDes); |
|
1064 break; |
|
1065 #endif // SYMBIAN_TCPIPDHCP_UPDATE |
|
1066 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
1067 case KConnGetDhcpHdrSname: |
|
1068 { |
|
1069 /* |
|
1070 Extract the server hostname |
|
1071 **/ |
|
1072 GetDhcpHdrSnameL(*aDes); |
|
1073 break; |
|
1074 } |
|
1075 |
|
1076 case KConnGetDhcpHdrSiaddr: |
|
1077 { |
|
1078 /* |
|
1079 Extract the server IPAddress |
|
1080 **/ |
|
1081 GetDhcpHdrSiaddrL(*aDes); |
|
1082 break; |
|
1083 } |
|
1084 |
|
1085 |
|
1086 case KConnGetTftpServerAddr: |
|
1087 { |
|
1088 /* |
|
1089 Extract the TFTP Server Address |
|
1090 **/ |
|
1091 HandleGetTftpServerAddrL(*aDes); |
|
1092 if (iDhcpStateMachine->iDhcpInformAckPending) |
|
1093 { |
|
1094 return ETrue; |
|
1095 } |
|
1096 break; |
|
1097 } |
|
1098 |
|
1099 case KConnGetTftpServerName: |
|
1100 { |
|
1101 /* |
|
1102 Extract Tftp Server Name |
|
1103 **/ |
|
1104 HandleGetTftpServerNameL(*aDes); |
|
1105 if (iDhcpStateMachine->iDhcpInformAckPending) |
|
1106 { |
|
1107 return ETrue; |
|
1108 } |
|
1109 break; |
|
1110 } |
|
1111 |
|
1112 case KConnDhcpGetMultipleParams : |
|
1113 { |
|
1114 HandleGetMultipleParamsL(*aDes); |
|
1115 if (iDhcpStateMachine->iDhcpInformAckPending) //all options found ..copy the message |
|
1116 { |
|
1117 return ETrue; //make DHCPINFORM |
|
1118 } |
|
1119 break; |
|
1120 } |
|
1121 #ifdef SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
1122 case KConnDhcpSetHwAddressParams: |
|
1123 { |
|
1124 //Extract the Hardware address from the received descriptor and preserve it for future reference. |
|
1125 Uint64 hwAddress = 0; |
|
1126 TInt length = aDes->Length(); |
|
1127 if(length > KHwAddrLength) |
|
1128 { |
|
1129 // Leave the routine if the hwAddress length is not of the standard |
|
1130 User::Leave(KErrArgument); |
|
1131 } |
|
1132 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("IOCTL Inserting the MAC address"))); |
|
1133 for(TInt index = 0; index < length; index++) |
|
1134 { |
|
1135 hwAddress <<= KEightBit; |
|
1136 hwAddress += (*aDes)[index]; |
|
1137 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("%x "), (*aDes)[index])); |
|
1138 } |
|
1139 iDhcpHwAddrManager->Insert(hwAddress); |
|
1140 } |
|
1141 break; |
|
1142 #endif //SYMBIAN_NETWORKING_ADDRESS_PROVISION |
|
1143 #endif // SYMBIAN_NETWORKING_DHCP_MSG_HEADERS |
|
1144 |
|
1145 default: |
|
1146 User::Leave(KErrNotSupported); |
|
1147 } |
|
1148 } |
|
1149 |
|
1150 return EFalse; // request was serviced |
|
1151 } |
|
1152 |
|
1153 |
|
1154 TInt CDHCPControl::HandleClientRequestL(TUint aName, TInt aValue) |
|
1155 { |
|
1156 /** |
|
1157 * Handles client requests made through RConnection |
|
1158 * are handled here. Currently aValue is used to set the |
|
1159 * user defined renew timeout |
|
1160 * @internalTechnology |
|
1161 */ |
|
1162 TBool deferAllowed = !iMessage; |
|
1163 TInt deferred = EFalse; |
|
1164 |
|
1165 if (iDhcpStateMachine) |
|
1166 { |
|
1167 switch (aName) |
|
1168 { |
|
1169 case KConnAddrRelease: |
|
1170 if (deferAllowed && !iDhcpStateMachine->IsGettingCfgInfoOnly()) |
|
1171 { |
|
1172 iTimer->Cancel(); |
|
1173 iDhcpStateMachine->Cancel(); |
|
1174 iDhcpStateMachine->iMaxRetryCount = 3; |
|
1175 iValidMsg.Close(); |
|
1176 |
|
1177 // Check to see if we need to ask the DHCP server to release the address |
|
1178 // or if we have not yet acquired an address and should cancel any operation |
|
1179 // in progress. |
|
1180 if( ( iState == EInitialised ) || ( iState == EReconfigureInProgress ) ) |
|
1181 { |
|
1182 iDhcpStateMachine->StartReleaseL( this ); |
|
1183 iState = EReleaseInProgress; |
|
1184 deferred = ETrue; |
|
1185 } |
|
1186 else |
|
1187 { |
|
1188 iState = EEnd; |
|
1189 |
|
1190 // Listen for Link Local address. |
|
1191 // Assignment process has been cancelled so we unblock our client. |
|
1192 if (iDhcpConfigListener && iDhcpConfigListener->HaveLinkLocal()) |
|
1193 { |
|
1194 CompleteClientConfigureMessage(KErrNone); |
|
1195 } |
|
1196 } |
|
1197 } |
|
1198 if (iDhcpStateMachine->IsGettingCfgInfoOnly()) |
|
1199 { |
|
1200 deferred = KErrNotSupported; |
|
1201 } |
|
1202 break; |
|
1203 case KConnAddrRenew: |
|
1204 if (deferAllowed && !iDhcpStateMachine->IsGettingCfgInfoOnly()) |
|
1205 { |
|
1206 iTimer->Cancel(); |
|
1207 iDhcpStateMachine->Cancel(); |
|
1208 iDhcpStateMachine->iMaxRetryCount = 3; //If server doesn't respond after 3 attempts, a rebind is initiated..Pls not Ipv6 calculates its own retry values |
|
1209 |
|
1210 // Check to see if we need to ask the DHCP server to renew the address |
|
1211 // or if we have not yet acquired an address and should start |
|
1212 // initialisation again (i.e., the lease has been released). |
|
1213 if( ( iState == EInitInProgress ) || ( iState == EReleaseInProgress ) || ( iState == EEnd ) ) |
|
1214 { |
|
1215 iDhcpStateMachine->StartInitL(this,iConfigType == EConfigIPAddress ? CDHCPStateMachine::ESubsequentCalls : CDHCPStateMachine::EFirstCall,aValue); |
|
1216 iState = EInitInProgress; |
|
1217 iInitStartedByRenew = ETrue; |
|
1218 } |
|
1219 else |
|
1220 { |
|
1221 iDhcpStateMachine->StartRenewL(this,aValue); |
|
1222 iState = ERenewInProgress; |
|
1223 } |
|
1224 |
|
1225 deferred = ETrue; |
|
1226 } |
|
1227 if (iDhcpStateMachine->IsGettingCfgInfoOnly()) |
|
1228 { |
|
1229 deferred = KErrNotSupported; |
|
1230 } |
|
1231 break; |
|
1232 default: |
|
1233 User::Leave(KErrNotSupported); |
|
1234 } |
|
1235 } |
|
1236 else |
|
1237 { |
|
1238 // ConfigureL must have left before it could create a state machine |
|
1239 // object, doing this is the only safe way to stop dereferencing |
|
1240 // a possibly null pointer. |
|
1241 User::Leave(KErrAbort); |
|
1242 } |
|
1243 |
|
1244 return deferred; |
|
1245 } |
|
1246 |
|
1247 TInt CDHCPControl::HandleClientRequestL(TUint aName) |
|
1248 /** |
|
1249 * Handles client requests made through RConnection |
|
1250 * are handled here. These are obtaining the ip address, |
|
1251 * the dhcp server ip address, the remaining lease time |
|
1252 * and also renewing and releasing the lease |
|
1253 * |
|
1254 * @internalTechnology |
|
1255 */ |
|
1256 { |
|
1257 return CDHCPControl::HandleClientRequestL(aName,0); |
|
1258 } |
|
1259 |
|
1260 void CDHCPControl::UpdateDns(TDesC8* aHostName, TDesC8* aDomainName) |
|
1261 /** |
|
1262 * UpdateDNS function |
|
1263 * |
|
1264 * Poke the DNS update dll to perform its |
|
1265 * dynamic dns update. However, this is DHCP |
|
1266 * and we can't handle failure cases for DNS |
|
1267 * so we ignore any errors as it's not our job |
|
1268 * |
|
1269 * @internalTechnology |
|
1270 */ |
|
1271 { |
|
1272 __UHEAP_MARK; |
|
1273 CDnsUpdateIf* pUpdate = NULL; |
|
1274 TRAPD(ret,pUpdate = CDnsUpdateIf::NewL(); |
|
1275 pUpdate->Update(iInterfaceName, aHostName, aDomainName)); |
|
1276 if (ret!=KErrNone) |
|
1277 { |
|
1278 __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPControl::UpdateDns error: %d"),ret)); |
|
1279 } |
|
1280 delete pUpdate; |
|
1281 REComSession::FinalClose(); |
|
1282 __UHEAP_MARKEND; |
|
1283 } |
|
1284 |
|
1285 #ifdef SYMBIAN_NETWORKING_DHCPSERVER |
|
1286 void CDHCPControl::HandleSetRawOptionCodeL(TDes8* /*aDes*/) |
|
1287 { |
|
1288 } |
|
1289 #endif // SYMBIAN_NETWORKING_DHCPSERVER |
|
1290 |