tcpiputils/dhcp/src/DHCPStateMachine.cpp
changeset 0 af10295192d8
child 25 d15a50675083
child 27 4214adf9e0d3
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements the DHCP statemachine helper functions
       
    15 // 
       
    16 //
       
    17 
       
    18 /**
       
    19  @file DHCPStateMachine.cpp
       
    20  @internalTechnology
       
    21 */
       
    22 
       
    23 #include "DHCPStates.h"
       
    24 #include "DHCPStatesDebug.h"
       
    25 #include "DHCPControl.h"
       
    26 #include "ExpireTimer.h"
       
    27 #include "DHCPMsg.h"
       
    28 #include <e32math.h>
       
    29 #include "DHCPServer.h"
       
    30 #include "in6_opt.h"
       
    31 #include "es_sock.h"
       
    32 
       
    33 CDHCPStateMachine::~CDHCPStateMachine()
       
    34 /**
       
    35   * Destructor of the If base class
       
    36   *
       
    37   * @internalTechnology
       
    38   *
       
    39   */
       
    40 	{
       
    41 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::~CDHCPStateMachine")));
       
    42 	Cancel();
       
    43 	delete iDhcpMessage;
       
    44 	delete iMessageSender;
       
    45 	delete iTimer;
       
    46 	delete iHostName;
       
    47 	delete iDomainName;
       
    48 #ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
       
    49 	iSavedExtraParameters.Close();
       
    50 #endif //SYMBIAN_NETWORKING_DHCP_MSG_HEADERS	
       
    51 	iClientId.Close();
       
    52 	iSocket.Close();
       
    53 #ifdef SYMBIAN_NETWORKING_DHCPSERVER	
       
    54 	iSvrSocket.Close();
       
    55 	delete iDNSInformation;
       
    56 #endif // SYMBIAN_NETWORKING_DHCPSERVER	
       
    57 	}
       
    58 
       
    59 void CDHCPStateMachine::ConstructL()
       
    60 /**
       
    61   * Creates socket and connections for the object
       
    62   *
       
    63   *
       
    64   *	@internalTechnology
       
    65   *
       
    66   */
       
    67 	{
       
    68 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::ConstructL")));
       
    69 	
       
    70 #ifdef _DEBUG
       
    71 	// let's set debug properties to something
       
    72 	//  so they can be read immediately..
       
    73 	CDHCPStateMachine* const & iStateMachine = this;
       
    74 	CDHCPStateMachine* const & iDhcpStateMachine = iStateMachine;
       
    75 	DHCP_DEBUG_PUBLISH_READY(DHCPDebug::ENotReady);
       
    76 	DHCP_DEBUG_PUBLISH_STATE(DHCPDebug::EStateUnknown);
       
    77 #endif
       
    78 
       
    79 	iTimer = CExpireTimer::NewL();
       
    80 #ifdef SYMBIAN_NETWORKING_DHCPSERVER	
       
    81 	if(!iServerImpl) // Assemble client Ids only for DHCP client implementation
       
    82 		{
       
    83 #endif // SYMBIAN_NETWORKING_DHCPSERVER	
       
    84 	InitialiseSocketL();
       
    85 	AssembleClientIDsL();
       
    86 #ifdef SYMBIAN_NETWORKING_DHCPSERVER	
       
    87 		}
       
    88 	else
       
    89 		InitialiseServerSocketL();
       
    90 #endif // SYMBIAN_NETWORKING_DHCPSERVER			
       
    91 	}
       
    92 
       
    93 void CDHCPStateMachine::Start(MStateMachineNotify* aStateMachineNotify)
       
    94 /**
       
    95   * The Start function
       
    96   *
       
    97   * Starts the statemachine task
       
    98   *
       
    99   * @internalTechnology
       
   100   */
       
   101 {
       
   102    SetLastError( KErrNone );
       
   103    iReceiving = EFalse;
       
   104    iHistory = 0;
       
   105 	SetActiveEvent(iFirstState);
       
   106 	if ( !aStateMachineNotify )
       
   107 		{//no notifier specified => leave the current one unchanged
       
   108 		aStateMachineNotify = iStateMachineNotify;
       
   109 		}
       
   110 	CStateMachine::Start(NULL, NULL, aStateMachineNotify);
       
   111 }
       
   112 
       
   113 void CDHCPStateMachine::CloseNSendMsgL(TRequestStatus& aStatus, CDHCPStateMachine::EAddressType aEAddressType)
       
   114 /**
       
   115   * Handles sending of packets for this object
       
   116   *
       
   117   * @internalTechnology
       
   118   *
       
   119   */
       
   120 	{
       
   121 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::CloseNSendMsgL")));
       
   122    	PrepareToSendL(aEAddressType);
       
   123   	iMessageSender->Cancel();
       
   124 	
       
   125 	GetServerAddress(iSocketAddr);
       
   126 	AddScopeToAddrL(iSocketAddr);
       
   127 
       
   128 #ifdef _DEBUG
       
   129 	THostName addrDes;
       
   130 	iSocketAddr.Output(addrDes);	
       
   131 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, 
       
   132 		_L("CDHCPStateMachine::CloseNSendMsgL - Sending message to %S%%%d"), &addrDes, iSocketAddr.Scope()));
       
   133 #endif
       
   134 
       
   135 	iSocket.SendTo(iDhcpMessage->Message(), iSocketAddr, 0, aStatus);
       
   136 	}
       
   137 
       
   138 #ifdef SYMBIAN_NETWORKING_DHCPSERVER
       
   139 void CDHCPStateMachine::CloseNSendServerMsgL(TRequestStatus& aStatus, CDHCPStateMachine::EAddressType aEAddressType)
       
   140 /**
       
   141   * Handles sending of packets for this object
       
   142   *
       
   143   * @internalTechnology
       
   144   *
       
   145   */
       
   146 	{
       
   147 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::CloseNSendMsgL")));
       
   148 
       
   149 
       
   150    	PrepareToSendServerMsgL(aEAddressType);
       
   151   	iMessageSender->Cancel();
       
   152 
       
   153 	GetClientAddress(iSrvSocketAddr);
       
   154 	AddScopeToClientAddrL(iSrvSocketAddr);
       
   155 
       
   156 #ifdef _DEBUG
       
   157 	THostName addrDes;
       
   158 	iSrvSocketAddr.Output(addrDes);	
       
   159 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, 
       
   160 		_L("CDHCPStateMachine::CloseNSendServerMsgL - Sending message to %S%%%d"), &addrDes, iSrvSocketAddr.Scope()));
       
   161 #endif
       
   162 
       
   163 	iSvrSocket.SendTo(iDhcpMessage->Message(), iSrvSocketAddr, 0, aStatus);
       
   164 	}
       
   165 	
       
   166 void CDHCPStateMachine::GetClientAddress( TInetAddr& /*aAddress*/ )
       
   167 /**
       
   168   * GetClientAddress
       
   169   *
       
   170   * Null implementation
       
   171   *
       
   172   * @internalTechnology	
       
   173 */
       
   174 	{
       
   175 	}	
       
   176 	
       
   177 #ifdef SYMBIAN_DNS_PROXY	
       
   178 TInetAddr CDHCPStateMachine::GetListenerAddress()
       
   179 	{
       
   180 	return iCurrentAddress;
       
   181 	}
       
   182 #endif
       
   183 		
       
   184 void CDHCPStateMachine::InitServerStateMachineL(MStateMachineNotify* /*aStateMachineNotify*/)
       
   185 /**
       
   186   * InitServerStateMachineL
       
   187   *
       
   188   * Null implementation
       
   189   *
       
   190   * @internalTechnology
       
   191   */
       
   192 	{
       
   193 	}	
       
   194 	
       
   195 void CDHCPStateMachine::InitServerBinding(MStateMachineNotify* /*aStateMachineNotify*/)		
       
   196 	{
       
   197 	
       
   198 	}
       
   199 	
       
   200 #endif // SYMBIAN_NETWORKING_DHCPSERVER
       
   201 
       
   202 void CDHCPStateMachine::CloseNSendMsgL(TTimeIntervalSeconds aSecs, TInt aMaxRetryCount, CDHCPStateMachine::EAddressType aEAddressType)
       
   203 /**
       
   204   * Handles sending of packets for this object
       
   205   *
       
   206   * @internalTechnology
       
   207   *
       
   208   */
       
   209 	{
       
   210 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::CloseNSendMsgL")));
       
   211    	PrepareToSendL(aEAddressType);
       
   212 	iMessageSender->Cancel();
       
   213 	
       
   214 	TInetAddr addr;		
       
   215 	GetServerAddress( addr );
       
   216 	AddScopeToAddrL(addr);
       
   217 	
       
   218 #ifdef _DEBUG
       
   219 	THostName addrDes;
       
   220 	addr.Output(addrDes);	
       
   221 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, 
       
   222 		_L("CDHCPStateMachine::CloseNSendMsgL - Sending message to %S%%%d"), &addrDes, addr.Scope()));
       
   223 #endif
       
   224 
       
   225 	if (FastTimeoutDuringInform())	// true only when InformNegotiationIsRequiredForConnectionStartCompletion is ETrue
       
   226 		{
       
   227 		iMessageSender->SendL(addr, iDhcpMessage->Message(), (aSecs.Int() * KMicrosecondsInSecs) / 14, aMaxRetryCount);
       
   228 		}
       
   229 	else
       
   230 		{
       
   231 		iMessageSender->SendL(addr, iDhcpMessage->Message(), aSecs.Int() * KMicrosecondsInSecs, aMaxRetryCount);	
       
   232 		}
       
   233 	}
       
   234 
       
   235 TInt CDHCPStateMachine::MSReportError(TInt aError)
       
   236 /**
       
   237   * Report an error properly
       
   238   *
       
   239   * @internalTechnology
       
   240   */
       
   241 	{
       
   242 	Cancel();
       
   243 
       
   244 	SetLastError(aError);
       
   245 	OnCompletion();
       
   246 
       
   247 	return aError;
       
   248 	}
       
   249 
       
   250 void CDHCPStateMachine::Cancel()
       
   251 /**
       
   252   * Cancel the state machine's activities
       
   253   *
       
   254   * @internalTechnology
       
   255   */
       
   256 	{
       
   257 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::Cancel")));
       
   258 	CancelMessageSender();
       
   259 	iSocket.Close();
       
   260 #ifdef SYMBIAN_NETWORKING_DHCPSERVER	
       
   261 	iSvrSocket.Close();
       
   262 #endif // SYMBIAN_NETWORKING_DHCPSERVER	
       
   263 	CancelTimer();
       
   264 	CStateMachine::Cancel(KErrNone);
       
   265 	delete iFirstState;
       
   266 	iFirstState = NULL;
       
   267 	iFastTimeout = EFalse;	// reset iFastTimeout
       
   268 	iMaxRetryCount = KInfinity;//reset
       
   269 	}
       
   270 
       
   271 void CDHCPStateMachine::DoCancel()
       
   272 /**
       
   273   * Implements a default docancel for the connection object
       
   274   *
       
   275   * @internalTechnology
       
   276   */
       
   277 	{
       
   278 	// we have to cancel send and recv independently as cancelAll()
       
   279 	// doesn't satisfy us, only supporting read, write, ioctl, connect,
       
   280 	// accept and shutdown...:-(
       
   281 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::DoCancel")));
       
   282 	if (iSocket.SubSessionHandle())
       
   283 		{
       
   284 		// check that the socket is open
       
   285 		// and if it is then we need to cancel things on it
       
   286 		iSocket.CancelRecv();
       
   287 		}
       
   288 #ifdef SYMBIAN_NETWORKING_DHCPSERVER		
       
   289 	if(iSvrSocket.SubSessionHandle())
       
   290 		{
       
   291 		iSvrSocket.CancelRecv();
       
   292 		}
       
   293 #endif // SYMBIAN_NETWORKING_DHCPSERVER		
       
   294 	/*	iAsyncCancelHandler is set by the DHCP State that assumes ownership of the 
       
   295 		RequestStatus object of CDHCPStateMachine 				 
       
   296 	*/
       
   297 	 if(iAsyncCancelHandler)
       
   298 		{
       
   299 		iAsyncCancelHandler->Cancel();
       
   300 		}
       
   301 	}
       
   302 #ifdef SYMBIAN_NETWORKING_DHCPSERVER
       
   303 void CDHCPStateMachine::FetchServerAddressL()
       
   304 /**
       
   305   * This function is used to get the server's address (interface address)
       
   306   *
       
   307   */
       
   308 	{
       
   309 	if(!iSvrSocket.SubSessionHandle())
       
   310 		InitialiseServerSocketL();
       
   311 	
       
   312 	TPckgBuf<TSoInetInterfaceInfo> opt;
       
   313 	while (iSvrSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
       
   314 		{
       
   315 		if (opt().iName == iInterfaceName)
       
   316 			{
       
   317 			iCurrentAddress = opt().iAddress;
       
   318 			break;
       
   319 			}
       
   320 		}
       
   321    }
       
   322    
       
   323 void CDHCPStateMachine::SetDNSInformation(TDes8* aDNSInfo)	
       
   324 	{
       
   325 	delete iDNSInformation;
       
   326 	iDNSInformation = NULL;
       
   327 	
       
   328 	iDNSInformation = HBufC8::NewL(aDNSInfo->Length());
       
   329 	iDNSInformation->Des() = *aDNSInfo;
       
   330 	}   
       
   331 	
       
   332 TBool CDHCPStateMachine::CheckNetworkId()
       
   333 /**
       
   334   * This function compares the NetworkIds of the client and server
       
   335   *
       
   336   */	
       
   337 	{
       
   338 	iInformClientAddr.SetV4MappedAddress(iCiaddr);
       
   339 
       
   340 	if ((iInformClientAddr.Address() & KInetAddrNetMaskC) == 
       
   341 			(iCurrentAddress.Address() & KInetAddrNetMaskC))		
       
   342 		{
       
   343 		return ETrue;		
       
   344 		}
       
   345 	else
       
   346 		{
       
   347 		return EFalse;
       
   348 		}	
       
   349 	}   
       
   350 #endif // SYMBIAN_NETWORKING_DHCPSERVER
       
   351 
       
   352 void CDHCPStateMachine::FetchHWAddress()
       
   353 /**
       
   354   * Fetches hardware address from the interface
       
   355   *
       
   356   */
       
   357 	{
       
   358 	TPckgBuf<TSoInetInterfaceInfo> opt;
       
   359 	while (iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
       
   360 		{
       
   361 		if (opt().iName == iInterfaceName)
       
   362 			{
       
   363 			iHardwareAddr = opt().iHwAddr;
       
   364 			if(iHardwareAddr.Length() <= KHwAddrOffset)
       
   365 				{
       
   366 				// the hardware address came back too short
       
   367    		 		//  to be a valid TSockAddr.. so we'll treat it as an empty value
       
   368 				iHardwareAddr.SetFamily(KAFUnspec);
       
   369 				iHardwareAddr.SetLength(KHwAddrOffset);
       
   370 				}
       
   371 			break;
       
   372 			}
       
   373 		}
       
   374    }
       
   375 
       
   376 
       
   377 void CDHCPStateMachine::StartTimer(TTimeIntervalSeconds aSeconds, MExpireTimer& aExpireTimer)
       
   378 /**
       
   379   * Give the tcp/ip6 stack time to perform
       
   380   * its gratuitous ARP...
       
   381   *
       
   382   * @internalTechnology
       
   383   */
       
   384 	{
       
   385 	CancelTimer();
       
   386 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::StartTimerL")));
       
   387 
       
   388 	iTimer->After(aSeconds, aExpireTimer);
       
   389 	}
       
   390 
       
   391 void CDHCPStateMachine::StartTimer( TTimeIntervalMicroSeconds32 aMicroSeconds, MExpireTimer& aExpireTimer)
       
   392 /**
       
   393   * Give the tcp/ip6 stack time to perform
       
   394   * its gratuitous ARP...
       
   395   *
       
   396   * @internalTechnology
       
   397   */
       
   398 	{
       
   399 	CancelTimer();
       
   400 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::StartTimerL")));
       
   401 
       
   402 	iTimer->After(aMicroSeconds, aExpireTimer);
       
   403 	}
       
   404 
       
   405 void CDHCPStateMachine::RemoveConfiguredAddress( const TSoInet6InterfaceInfo& aSoInet6InterfaceInfo )
       
   406 /**
       
   407   * This function can be called as a result of DAD failing
       
   408   * or the lease expiring! It removes the address from the interface
       
   409   * inside the TCP/IP6 stack as the address cannot continue to be used.
       
   410   *
       
   411   * @see "Implementation of IPv4/IPv6 Basic Socket API for Symbian OS"
       
   412   * document for explanation of TSoInet6InterfaceInfo and its use
       
   413   * @internalTechnology
       
   414   */
       
   415 	{
       
   416 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::RemoveConfiguredAddress")));
       
   417 	
       
   418 	TPckgBuf<TSoInet6InterfaceInfo> configInfo(aSoInet6InterfaceInfo);
       
   419 	// not interested in error
       
   420 	// how could we attempt to handle it anyway?...keep trying??? i think not...
       
   421 	// ensure that we have a socket to write down	
       
   422 	iSocket.Close();	
       
   423 	(void)iSocket.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection);
       
   424 	(void)iSocket.SetOpt(KSoInetConfigInterface, KSolInetIfCtrl, configInfo);	
       
   425 	// make socket invisible for interface counting
       
   426 	(void)iSocket.SetOpt(KSoKeepInterfaceUp, KSolInetIp, 0);
       
   427 	}
       
   428 
       
   429 void CDHCPStateMachine::ConfigureInterfaceL( const TSoInet6InterfaceInfo& aInterfaceInfo )
       
   430 /**
       
   431   * Set the interface IP address and other params
       
   432   * into the TCP/IP6 stack.
       
   433   *
       
   434   * What we set depends on the setup
       
   435   * in commDB for the service.  If ipAddressFromServer
       
   436   * is true then we set the ip address that has
       
   437   * been assigned by DHCP, along with the netmask and gateway.
       
   438   * If ipAddressFromServer is false, then we set the static ip
       
   439   * address as long as it has been okayed by the DHCP server after
       
   440   * we have sent an inform.  We will then set the netmask and gateway
       
   441   * choosing from those in commDB if they have been given values, or 
       
   442   * those returned in the DHCP Server ACK if a zero address is in commDB
       
   443   * The same principle applies to DNS Server addresses.
       
   444   *
       
   445   * @internalTechnology
       
   446   */
       
   447 	{
       
   448 	
       
   449 	TPckgBuf<TSoInet6InterfaceInfo> configInfo(aInterfaceInfo);
       
   450 	
       
   451 
       
   452 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::ConfigureInterfaceL - KSoInetConfigInterface")));
       
   453 	
       
   454 	User::LeaveIfError(iSocket.SetOpt(KSoInetConfigInterface, KSolInetIfCtrl, configInfo));
       
   455 	}
       
   456 
       
   457 TInt CDHCPStateMachine::BindToSource()
       
   458 /**
       
   459   * Binds socket to newly assigned address for the interface
       
   460   *
       
   461   * @internalTechnology
       
   462   */
       
   463 	{
       
   464 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::BindToSourceL")));
       
   465 	iSocket.Close();	// destroy the old socket
       
   466 	
       
   467 	UpdateHistory(CDHCPState::EBindToSource);
       
   468 	// now start a new one.
       
   469 	// might be nice if we left here if the socket open fails...but nobody's perfect...
       
   470    // PS: cannot leave here the failure doesn't mean exception here see the usage....
       
   471 	TInt err = iSocket.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection);
       
   472 	// make socket invisable for interface counting
       
   473 	if (err == KErrNone)
       
   474 		{
       
   475 		err = iSocket.SetOpt(KSoKeepInterfaceUp, KSolInetIp, 0);
       
   476 		}
       
   477 		
       
   478     if (err == KErrNone)       //PDEF122482: Enabling the ReUseAddr option.
       
   479 	    {
       
   480 	    err = iSocket.SetOpt(KSoReuseAddr, KSolInetIp, 1);
       
   481 	    }			
       
   482 	
       
   483 	if (err == KErrNone)
       
   484 		{
       
   485         TInetAddr bindTo;        
       
   486         AssignAddresses( bindTo, iCurrentAddress ); 
       
   487 
       
   488         err = iSocket.Bind(bindTo);
       
   489         if (err==KErrNone)
       
   490 	        {
       
   491 	        // we are finished with this socket, 
       
   492 	        // release it so as not to hold esock open
       
   493 	        iSocket.Close();
       
   494 	        }
       
   495 		}
       
   496 	return err;
       
   497 	}
       
   498 
       
   499 
       
   500 TUint32 CDHCPStateMachine::GetNetworkIdL() const
       
   501 	{	
       
   502 	TUint32 networkId;
       
   503 	_LIT(KIapNetwork, "IAP\\IAPNetwork");
       
   504 	User::LeaveIfError(iConnection.GetIntSetting(KIapNetwork, networkId));
       
   505 	
       
   506 	return networkId;
       
   507 	}
       
   508 
       
   509 void CDHCPStateMachine::AddScopeToAddrL(TInetAddr& addr)
       
   510 	{
       
   511 	TPckgBuf<TSoInetIfQuery> queryBuf;
       
   512 	queryBuf().iName = iInterfaceName;		
       
   513 	User::LeaveIfError(iSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, queryBuf));
       
   514 	
       
   515 	const TUint s = addr.Ip6Address().Scope() - 1;
       
   516 
       
   517 	if (s < 16)
       
   518 		{
       
   519 		addr.SetScope(queryBuf().iZone[s]);
       
   520 		}
       
   521 	}
       
   522 
       
   523 #ifdef SYMBIAN_NETWORKING_DHCPSERVER
       
   524 void CDHCPStateMachine::AddScopeToClientAddrL(TInetAddr& addr)
       
   525 	{
       
   526 	TPckgBuf<TSoInetIfQuery> queryBuf;
       
   527 	queryBuf().iName = iInterfaceName;		
       
   528 	User::LeaveIfError(iSvrSocket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, queryBuf));
       
   529 	
       
   530 	const TUint s = addr.Ip6Address().Scope() - 1;
       
   531 
       
   532 	if (s < 16)
       
   533 		{
       
   534 		addr.SetScope(queryBuf().iZone[s]);
       
   535 		}
       
   536 	}
       
   537 // Set when the DHCP server implementation is being used	
       
   538 void CDHCPStateMachine::SetServerState(TBool aServerImpl)	
       
   539 	{
       
   540 	iServerImpl = aServerImpl;
       
   541 	}
       
   542 	
       
   543 TInt CDHCPStateMachine::BindServerInterface()
       
   544 /**
       
   545   * Binds socket to newly assigned address for the interface
       
   546   *
       
   547   * @internalTechnology
       
   548   */
       
   549 	{
       
   550 	__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("CDHCPStateMachine::BindServerInterface")));
       
   551 	iSvrSocket.Close();	// destroy the old socket
       
   552 	
       
   553 	// now start a new one.
       
   554 	TInt err = iSvrSocket.Open(iEsock, KAfInet, KSockDatagram, KProtocolInetUdp, iConnection);
       
   555 	// make socket invisable for interface counting
       
   556 	if (err == KErrNone)
       
   557 		{
       
   558 		TInt err = iSvrSocket.SetOpt(KSoKeepInterfaceUp, KSolInetIp, 0);
       
   559 		}
       
   560 
       
   561 	if (err == KErrNone)
       
   562 		{
       
   563         TInetAddr bindTo;        
       
   564         AssignAddresses( bindTo, iCurrentAddress );
       
   565         err = iSvrSocket.Bind(bindTo);
       
   566 		}
       
   567 	return err;
       
   568 	}
       
   569 
       
   570 	
       
   571 TInetAddr CDHCPStateMachine::GetInterfaceServerGlobalAddress()
       
   572 /**
       
   573   * Are any of the addresses on the interface global addresses?
       
   574   *  If so, DHCP might decide not to attempt to discover an address.
       
   575   *
       
   576   * Returns unspecified address if no global address present.
       
   577   */
       
   578 	{
       
   579 	TPckgBuf<TSoInetInterfaceInfo> opt;
       
   580 	if (iSvrSocket.SubSessionHandle() == 0)
       
   581 		{
       
   582 		InitialiseServerSocketL();
       
   583 		}
       
   584 	iSvrSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
       
   585 	__CFLOG_STMT(TBuf<512> addrStr;);
       
   586 	while (iSvrSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
       
   587 		{
       
   588 		if (opt().iName == iInterfaceName)
       
   589 			{
       
   590 			TInetAddr& addr = opt().iAddress;
       
   591 			__CFLOG_STMT(addr.Output(addrStr););
       
   592 			if ( ! addr.IsLinkLocal())
       
   593 				{
       
   594 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L("Global address %S found on interface %S"),&addrStr,&iInterfaceName));
       
   595 				return addr;
       
   596 				}
       
   597 			else
       
   598 				{
       
   599 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L("Linklocal address %S found on interface %S"),&addrStr,&iInterfaceName));
       
   600 				}
       
   601 			break;
       
   602 			}
       
   603 		}
       
   604 	return TInetAddr(); // unspecified
       
   605 	}
       
   606 
       
   607 
       
   608 
       
   609 		
       
   610 #endif // SYMBIAN_NETWORKING_DHCPSERVER
       
   611 	
       
   612 TInetAddr CDHCPStateMachine::GetInterfaceGlobalAddress()
       
   613 /**
       
   614   * Are any of the addresses on the interface global addresses?
       
   615   *  If so, DHCP might decide not to attempt to discover an address.
       
   616   *
       
   617   * Returns unspecified address if no global address present.
       
   618   */
       
   619 	{
       
   620 #ifdef SYMBIAN_NETWORKING_DHCPSERVER	
       
   621 	if(iServerImpl)
       
   622 		{
       
   623 		return GetInterfaceServerGlobalAddress();
       
   624 		}
       
   625 	else
       
   626 		{
       
   627 #endif // SYMBIAN_NETWORKING_DHCPSERVER	
       
   628 	
       
   629 	TPckgBuf<TSoInetInterfaceInfo> opt;
       
   630 	if (iSocket.SubSessionHandle() == 0)
       
   631 		{
       
   632 		InitialiseSocketL();
       
   633 		}
       
   634 	iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
       
   635 	__CFLOG_STMT(TBuf<512> addrStr;);
       
   636 	while (iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
       
   637 		{
       
   638 		if (opt().iName == iInterfaceName)
       
   639 			{
       
   640 			TInetAddr& addr = opt().iAddress;
       
   641 			__CFLOG_STMT(addr.Output(addrStr););
       
   642 			if ( ! addr.IsLinkLocal())
       
   643 				{
       
   644 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L("Global address %S found on interface %S"),&addrStr,&iInterfaceName));
       
   645 				return addr;
       
   646 				}
       
   647 			else
       
   648 				{
       
   649 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L("Linklocal address %S found on interface %S"),&addrStr,&iInterfaceName));
       
   650 				}
       
   651 			break;
       
   652 			}
       
   653 		}
       
   654 	return TInetAddr(); // unspecified
       
   655 	
       
   656 #ifdef SYMBIAN_NETWORKING_DHCPSERVER
       
   657 		}
       
   658 #endif // SYMBIAN_NETWORKING_DHCPSERVER				
       
   659 	}
       
   660 
       
   661 
       
   662 TBool CDHCPStateMachine::DoesInterfaceKnowAnyDNSServers()
       
   663 /**
       
   664   * Does the interface know of any DNS servers?
       
   665   */
       
   666 	{
       
   667 	TPckgBuf<TSoInetInterfaceInfo> opt;
       
   668 	if (iSocket.SubSessionHandle() == 0)
       
   669 		{
       
   670 		InitialiseSocketL();
       
   671 		}
       
   672 	iSocket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
       
   673 	__CFLOG_STMT(TBuf<512> addrStr;);
       
   674 	while (iSocket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, opt) == KErrNone)
       
   675 		{
       
   676 		if (opt().iName == iInterfaceName)
       
   677 			{
       
   678 			TInetAddr& addr = opt().iNameSer1;
       
   679 			__CFLOG_STMT(addr.Output(addrStr););
       
   680 			if ( ! addr.IsUnspecified() )
       
   681 				{
       
   682 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L("DNS server %S found on interface %S"),&addrStr,&iInterfaceName));
       
   683 				return ETrue;
       
   684 				}
       
   685 			else
       
   686 				{
       
   687 				__CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L("No DNS servers already set on interface %S (prior to DHCP)"),&iInterfaceName));
       
   688 				}
       
   689 			break;
       
   690 			}
       
   691 		}
       
   692 	return EFalse;
       
   693 	}
       
   694 
       
   695 
       
   696 
       
   697 
       
   698 TDhcpRnd::TDhcpRnd():iXid(0)
       
   699 /**
       
   700   * Constructor for this little random number 
       
   701   * class that creates us a random transaction id
       
   702   *
       
   703   * @internalTechnology
       
   704   */
       
   705 	{
       
   706 	TTime now;
       
   707 	now.HomeTime();
       
   708 	iSeed = now.Int64();
       
   709 	}
       
   710 
       
   711 TInt TDhcpRnd::Rnd(TInt aMin, TInt aMax)
       
   712 /**
       
   713   * Utility class function to generated a real
       
   714   * random number
       
   715   *
       
   716   * @internalTechnology
       
   717   */
       
   718 	{
       
   719 	return Math::Rand(iSeed)%(aMax-aMin+1)+aMin;
       
   720 	}