tcpiputils/dhcp/src/DHCPControl.cpp
changeset 0 af10295192d8
child 61 2fc972553898
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     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