linklayerprotocols/pppnif/SPPP/PPPLCP.CPP
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2005-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 //
       
    15 
       
    16 #include <e32hal.h>
       
    17 #include <e32math.h>
       
    18 #include <f32file.h>
       
    19 #include <random.h>
       
    20 #include "PPPLOG.H"								// must appear before ss_log.h
       
    21 #include <comms-infras/ss_metaconnprov.h>
       
    22 #include <comms-infras/ss_log.h>				// for LOG_NODE_CREATE etc.
       
    23 #include "PPPLCP.H"
       
    24 #include "PPPAUTH.H"
       
    25 #include "PPPCCP.H"
       
    26 #include "PPPLRD.H"
       
    27 #include "MSCBCPC.H"
       
    28 #include "PPP_VER.H"
       
    29 #include "PppProg.h"
       
    30 #include <commsdattypeinfov1_1.h>
       
    31 #include <networking/ppplcp.h>
       
    32 #include "ncpip.h"
       
    33 #include "ncpip6.h"
       
    34 #include "PPPConfig.h"
       
    35 #include "pppmessages.h"
       
    36 #include <elements/nm_messages_base.h>
       
    37 #include <elements/nm_messages_child.h>
       
    38 #include <comms-infras/ss_nodemessages_dataclient.h>
       
    39 #include <comms-infras/ss_nodemessages_flow.h>
       
    40 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    41 #include <nifvar_internal.h>
       
    42 #endif
       
    43 
       
    44 using namespace Elements;
       
    45 using namespace Messages;
       
    46 using namespace MeshMachine;
       
    47 using namespace ESock;
       
    48 
       
    49 static const TInt KMinValueForMSCallBackCode=1000;
       
    50 
       
    51 //
       
    52 // PPP LCP
       
    53 //
       
    54 
       
    55 #ifdef __VC32__
       
    56 // warning C4355: 'this' : used in base member initializer list
       
    57 #pragma warning (disable:4355)
       
    58 #endif
       
    59 
       
    60 #if defined ESOCK_LOGGING_ACTIVE || defined SYMBIAN_TRACE_ENABLE
       
    61 _LIT8(KNif,"Ppp");
       
    62 #endif
       
    63 
       
    64 EXPORT_C CPppLcp* CPppLcp::NewL(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf)
       
    65 	{
       
    66 	CPppLcp* flow = new (ELeave) CPppLcp(aFactory, aSubConnId, aProtocolIntf);
       
    67 	return flow;
       
    68 	}
       
    69 
       
    70 // Registers as unknown initially as lists won't be initialised
       
    71 EXPORT_C CPppLcp::CPppLcp(ESock::CSubConnectionFlowFactoryBase& aFactory, const Messages::TNodeId& aSubConnId, ESock::CProtocolIntfBase* aProtocolIntf)
       
    72   : CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf), MPppFsm(this, EPppPhaseAll, KPppIdLcp), MPppOptionsExtender(),
       
    73     iInitialised(EFalse),
       
    74     iSavedError(KErrNone),
       
    75     iTerminateAction(MNifIfNotify::EDisconnect),
       
    76     iLastRequest(Messages::TNodeSignal::TMessageId()),
       
    77     iLastRequestErrored(EFalse)
       
    78 	{
       
    79     __FLOG_OPEN(KCFNodeTag, KNif);
       
    80 	LOG_NODE_CREATE1(KNif, CPppLcp, " [factory=%08x]", &aFactory);
       
    81     __DECLARE_FSM_NAME(_S("LCP"));
       
    82 	iRecvrList.SetOffset(_FOFF(MPppRecvr, iPppRecvrListLink));
       
    83     }
       
    84 
       
    85 #ifdef __VC32__
       
    86 #pragma warning (default:4355)
       
    87 #endif
       
    88 
       
    89 EXPORT_C CPppLcp::~CPppLcp()
       
    90 	{
       
    91 	PppNcpMsCbcpFactory::Delete( iPppMsCbcp );
       
    92 	iPppMsCbcp=NULL;
       
    93 	delete iRecvTimeRemMessage;
       
    94 	iRecvTimeRemMessage = NULL;
       
    95 	delete iRecvIdentification;
       
    96 	iRecvIdentification = NULL;
       
    97 
       
    98 	delete iPppLink;
       
    99 	iPppLink = NULL;
       
   100 
       
   101 // N.B.: HDLC link relies on iLogger
       
   102 #if defined (_DEBUG)
       
   103 	delete iLogger;
       
   104 #endif
       
   105 
       
   106 
       
   107 	delete iPppAcp;
       
   108 	iPppAcp = NULL;
       
   109     delete iCallbackInfo;
       
   110 	iCallbackInfo = NULL;
       
   111 	delete iCallbackIETFRequestPacket;
       
   112 	iCallbackIETFRequestPacket = NULL;
       
   113 	delete iPppCcp;
       
   114 	iPppCcp = NULL;
       
   115 	delete iPppLrd;
       
   116 	iPppLrd = NULL;
       
   117 	delete iContainerForDlls;
       
   118 	iContainerForDlls = NULL;
       
   119 
       
   120 	ASSERT(iBinder4 == NULL);
       
   121 	ASSERT(iBinder6 == NULL);
       
   122 
       
   123 	LOG_NODE_DESTROY(KNif, CPppLcp);
       
   124 
       
   125     __FLOG_CLOSE;
       
   126 	}
       
   127 
       
   128 //-=========================================================
       
   129 // Messages::ANode methods
       
   130 //-=========================================================
       
   131 
       
   132 EXPORT_C void CPppLcp::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
       
   133     {
       
   134 	/**
       
   135 	   These messages may be received in the middle of another request, such as start.
       
   136 	   Therefore they must be handled before the CSubConnectionFlowBase::ReceivedL so
       
   137 	   that they do not override the last request originator for that
       
   138 	*/	
       
   139    	if (TLinkMessage::ERealmId == aMessage.MessageId().Realm())
       
   140        	{
       
   141        	switch ((iLastRequest = aMessage.MessageId()).MessageId())
       
   142            	{
       
   143         case TLinkMessage::TAuthenticateResponse::EId:
       
   144 			{
       
   145         	AuthenticateResponseMessage();
       
   146         	break;
       
   147 			}
       
   148         case TLinkMessage::TAgentToFlowNotification::EId:
       
   149 			{
       
   150 			TLinkMessage::TAgentToFlowNotification& msg = static_cast<TLinkMessage::TAgentToFlowNotification&>(aMessage);
       
   151         	AgentToFlowNotification(msg.iValue);
       
   152         	break;
       
   153 			}
       
   154         default:
       
   155 	    	__FLOG_2(_L8("CPppLcp\tReceivedL() unexpected message received [%08x,%d]"), aMessage.MessageId().Realm(), aMessage.MessageId().MessageId());
       
   156 			PppPanic(EPppPanic_UnexpectedSCPRMessage);
       
   157         	}
       
   158         return;
       
   159         }
       
   160 	
       
   161 	CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage);
       
   162 	if (TEBase::ERealmId == aMessage.MessageId().Realm())
       
   163     	{
       
   164     	switch ((iLastRequest = aMessage.MessageId()).MessageId())
       
   165         	{
       
   166         case TEBase::TError::EId :
       
   167             SubConnectionError(static_cast<TEBase::TError&>(aMessage).iValue);
       
   168             break;
       
   169         case TEBase::TCancel::EId :
       
   170         	if (iMMState != EStarting)
       
   171 	        	{
       
   172 	        	User::Leave(KErrNotReady);
       
   173 	        	}
       
   174 			DoStopFlow(KErrCancel, MNifIfNotify::EDisconnect);
       
   175 			break;
       
   176         default:
       
   177 		    __FLOG_2(_L8("CPppLcp\tReceivedL() unexpected message received [%08x,%d]"), aMessage.MessageId().Realm(), aMessage.MessageId().MessageId());
       
   178 			PppPanic(EPppPanic_UnexpectedSCPRMessage);
       
   179 			}
       
   180 		return;
       
   181 		}
       
   182     else if (TEChild::ERealmId == aMessage.MessageId().Realm())
       
   183     	{
       
   184     	switch ((iLastRequest = aMessage.MessageId()).MessageId())
       
   185         	{
       
   186         case TEChild::TDestroy::EId :
       
   187             Destroy();
       
   188             break;
       
   189         default:
       
   190 		    __FLOG_2(_L8("CPppLcp\tReceivedL() unexpected message received [%08x,%d]"), aMessage.MessageId().Realm(), aMessage.MessageId().MessageId());
       
   191 			PppPanic(EPppPanic_UnexpectedSCPRMessage);
       
   192 			}
       
   193 		return;
       
   194 		}
       
   195     else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm())
       
   196     	{
       
   197     	switch ((iLastRequest = aMessage.MessageId()).MessageId())
       
   198         	{
       
   199         case TCFDataClient::TStart::EId :
       
   200             StartFlowL();
       
   201             break;
       
   202         case TCFDataClient::TStop::EId :
       
   203             StopFlow(static_cast<TCFDataClient::TStop&>(aMessage).iValue);
       
   204             break;
       
   205         case TCFDataClient::TProvisionConfig::EId:
       
   206         	ProvisionConfig(static_cast<TCFDataClient::TProvisionConfig&>(aMessage).iConfig);
       
   207         	break;
       
   208 	    case TCFDataClient::TBindTo::EId :
       
   209         	{
       
   210             TCFDataClient::TBindTo& bindToReq = message_cast<TCFDataClient::TBindTo>(aMessage);
       
   211             if (!bindToReq.iNodeId.IsNull())
       
   212              	{
       
   213              	User::Leave(KErrNotSupported);
       
   214              	}
       
   215             RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef());
       
   216 			}
       
   217             break;
       
   218         default:
       
   219 		    __FLOG_2(_L8("CPppLcp\tReceivedL() unexpected message received [%08x,%d]"), aMessage.MessageId().Realm(), aMessage.MessageId().MessageId());
       
   220 			PppPanic(EPppPanic_UnexpectedSCPRMessage);
       
   221 			}
       
   222 		return;
       
   223 		}
       
   224     else if (TCFFlow::ERealmId == aMessage.MessageId().Realm())
       
   225     	{
       
   226     	switch ((iLastRequest = aMessage.MessageId()).MessageId())
       
   227         	{
       
   228         case TCFFlow::TBlock::EId :
       
   229             if (iBinder4)
       
   230             	{
       
   231             	iBinder4->BlockFlow(MLowerControl::EDisableAllOtherBindersOnFlow);
       
   232             	}
       
   233             if (iBinder6)
       
   234             	{
       
   235             	iBinder6->BlockFlow(MLowerControl::EDisableAllOtherBindersOnFlow);
       
   236             	}
       
   237             break;
       
   238         case TCFFlow::TUnBlock::EId :
       
   239             if (iBinder4)
       
   240             	{
       
   241             	iBinder4->SendFlowOn();
       
   242             	}
       
   243             if (iBinder6)
       
   244             	{
       
   245             	iBinder6->SendFlowOn();
       
   246             	}
       
   247             break;
       
   248         default:
       
   249 		    __FLOG_2(_L8("CPppLcp\tReceivedL() unexpected message received [%08x,%d]"), aMessage.MessageId().Realm(), aMessage.MessageId().MessageId());
       
   250 			PppPanic(EPppPanic_UnexpectedSCPRMessage);
       
   251 			}
       
   252 		return;
       
   253 		}
       
   254     else if (TCFMessage::ERealmId == aMessage.MessageId().Realm())
       
   255     	{
       
   256 		__FLOG_2(_L8("CPppLcp\tReceivedL() unexpected message received [%08x,%d]"), aMessage.MessageId().Realm(), aMessage.MessageId().MessageId());
       
   257 		PppPanic(EPppPanic_UnexpectedSCPRMessage);
       
   258 		return;
       
   259 		}
       
   260     else if (TCFMessage::ERealmId == aMessage.MessageId().Realm())
       
   261     	{
       
   262     	switch ((iLastRequest = aMessage.MessageId()).MessageId())
       
   263         	{
       
   264         case TCFMessage::TStateChange::EId :
       
   265             __FLOG(_L8("WARNING: CPppLcp::\tReceivedL() - I have received a TStateChange and I have ignored it"));
       
   266             break;
       
   267         default:
       
   268 		    __FLOG_2(_L8("CPppLcp\tReceivedL() unexpected message received [%08x,%d]"), aMessage.MessageId().Realm(), aMessage.MessageId().MessageId());
       
   269 			PppPanic(EPppPanic_UnexpectedSCPRMessage);
       
   270 			}
       
   271 		return;
       
   272 		}
       
   273     }
       
   274 
       
   275 //-=========================================================
       
   276 // Methods for handling SCPR messages
       
   277 //-=========================================================
       
   278 
       
   279 EXPORT_C void CPppLcp::SubConnectionGoingDown()
       
   280     {
       
   281     }
       
   282 
       
   283 EXPORT_C void CPppLcp::SubConnectionError(TInt /*aError*/)
       
   284     {
       
   285     }
       
   286 
       
   287 EXPORT_C void CPppLcp::StartFlowL()
       
   288     {
       
   289     ASSERT(iMMState == 0);
       
   290 
       
   291 	if (iSavedError)
       
   292 		{
       
   293 		// Provisioning error has already occurred
       
   294 	    __FLOG_1(_L8("CPppLcp:\tStartFlowL() error %d"), iSavedError);
       
   295 		User::Leave(iSavedError);
       
   296 		}
       
   297 
       
   298     __FLOG(_L8("CPppLcp::\tStartFlowL()"));
       
   299 
       
   300 	User::LeaveIfError(DoStartFlow());
       
   301     iMMState = EStarting;
       
   302     }
       
   303 
       
   304 EXPORT_C void CPppLcp::StopFlow(TInt aError)
       
   305     {
       
   306     __FLOG_1(_L8("CPppLcp::\tStopFlow(%d)"), aError);
       
   307     iMMState = EStopping;
       
   308     DoStopFlow(aError, MNifIfNotify::EDisconnect);
       
   309     }
       
   310 
       
   311 EXPORT_C void CPppLcp::ProvisionConfig(const ESock::RMetaExtensionContainerC& aConfigData)
       
   312     {
       
   313     iSavedError = KErrNone;
       
   314 
       
   315     TRAPD(err, ProvisionConfigL(aConfigData));
       
   316     if (err)
       
   317         {
       
   318         __FLOG_1(_L8("CPppLcp::\tProvisionConfig(): error %d"), err);
       
   319         iSavedError = err;		// report error later on TCFDataClient::TStart message - there no response to TProvisionConfig message
       
   320         }
       
   321     }
       
   322 
       
   323 EXPORT_C void CPppLcp::Destroy()
       
   324     {
       
   325     // No-one should be bound to us from above if we are about to disappear.
       
   326     ASSERT(iBinder4 == NULL && iBinder6 == NULL);
       
   327 	DeleteThisFlow();
       
   328     }
       
   329 
       
   330 EXPORT_C void CPppLcp::AuthenticateResponseMessage()
       
   331 /**
       
   332 Process link specific messages.
       
   333 */
       
   334 	{
       
   335 	// Retrieve credentials from control side memory
       
   336 	ASSERT(iAgentProvision); //should have been cheked before attempting
       
   337 	                         //authentication.
       
   338 	iCredentials = iAgentProvision->Credentials();
       
   339 	ASSERT(iCredentials);
       
   340 	TInt authErr = KErrNone;
       
   341 	CPppAuthentication* p = iAuthenticate;
       
   342 	iAuthenticate = NULL;
       
   343 	if((authErr = iCredentials->GetResult())==KErrNone)
       
   344 		{
       
   345 		iAuthenticateDone = ETrue;
       
   346 		}
       
   347 	if (p)
       
   348     	{
       
   349     	//may have bailed out due to tear down in progress.
       
   350     	p->CallAuthenticateComplete(authErr);
       
   351     	}
       
   352 
       
   353 
       
   354 	if (authErr != KErrNone)
       
   355     	{
       
   356     	PostErrorMessage(authErr);
       
   357     	}
       
   358 	}
       
   359 
       
   360 EXPORT_C void CPppLcp::AgentToFlowNotification(TInt aNotificationId)
       
   361     {
       
   362     TInt err;
       
   363     if ((err = NotificationMessage(TAgentToNifEventType(aNotificationId))) != KErrNone)
       
   364         {
       
   365 		if (iMMState == EStarted)
       
   366 			{
       
   367 			PostFlowDownMessage(err);
       
   368 			}
       
   369 		else
       
   370 			{
       
   371 			PostErrorMessage(err);
       
   372 			}
       
   373         }
       
   374     }
       
   375 
       
   376 TInt CPppLcp::NotificationMessage(TAgentToNifEventType aNotificationId)
       
   377 	{
       
   378 	switch(aNotificationId)
       
   379 		{
       
   380 	case EAgentToNifEventTypeModifyInitialTimer:
       
   381 		// Notification destined for binders
       
   382 		if (iBinder4)
       
   383 			{
       
   384 			return iBinder4->Notification(aNotificationId);
       
   385 			}
       
   386 		if (iBinder6)
       
   387 			{
       
   388 			return iBinder6->Notification(aNotificationId);
       
   389 			}
       
   390 		break;
       
   391 
       
   392 	case EAgentToNifEventTypeDisableTimers:
       
   393 	case EAgentToNifEventTypeEnableTimers:
       
   394 		return Notification(aNotificationId, NULL);
       
   395 
       
   396 	case EAgentToNifEventTypeGetDataTransfer:
       
   397 		break;
       
   398 
       
   399 	default:
       
   400 		PppPanic(EPppPanic_UnexpectedSCPRMessage);
       
   401 		}
       
   402 	return KErrNotSupported;		// keep compiler happy
       
   403 	}
       
   404 
       
   405 
       
   406 //
       
   407 // Utility functions for sending messages to SCPR
       
   408 //
       
   409 void CPppLcp::PostProgressMessage(TInt aStage, TInt aError)
       
   410 	{
       
   411 	if (iLastStateChange.iStage != aStage || iLastStateChange.iError != aError)
       
   412 		{
       
   413 		//unsolicited send of TStateChange message
       
   414 		iSubConnectionProvider.PostMessage(Id(), TCFMessage::TStateChange(TStateChange(aStage, aError)).CRef());
       
   415 		iLastStateChange.iStage = aStage;
       
   416 		iLastStateChange.iError = aError;
       
   417 		}
       
   418 	}
       
   419 
       
   420 void CPppLcp::PostDataClientStartedMessage()
       
   421 	{
       
   422     #ifdef __FLOG_ACTIVE
       
   423 		TPtrC8 ptr = GetMMStateName();
       
   424 	   	__FLOG_1(_L8("CPppLcp:\tPostDataClientStartedMessage() - State: %S."), &ptr);
       
   425  	#endif
       
   426 
       
   427 	if (iMMState == EStarting)
       
   428     	{
       
   429     	iMMState = EStarted;
       
   430     	//respond to earlier start request
       
   431     	iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStarted().CRef());
       
   432     	}
       
   433     
       
   434     #ifdef __FLOG_ACTIVE
       
   435     	if(iMMState != EStarted)
       
   436     		{
       
   437 	 	   	__FLOG(_L8("ERROR: CPppLcp:\tPostDataClientStartedMessage() - LCP was unable to start"));
       
   438     		}
       
   439  	#endif
       
   440 
       
   441     __ASSERT_DEBUG(iMMState == EStarted, PppPanic(EPppPanic_LCPFailedToStart));
       
   442 	}
       
   443 
       
   444 void CPppLcp::PostFlowDownMessage(TInt aError)
       
   445 	{
       
   446     #ifdef __FLOG_ACTIVE
       
   447 		TPtrC8 ptr = GetMMStateName();
       
   448 	   	__FLOG_2(_L8("CPppLcp:\tPostFlowDownMessage() - Error: %d, State: %S."), aError, &ptr);
       
   449  	#endif
       
   450 
       
   451 	ASSERT(aError != KErrNone);
       
   452 	if (iMMState == EStopping)
       
   453 	    {
       
   454 	    if (!iLastRequestErrored)
       
   455 	    	{
       
   456 			// Unexpected termination so send TError message
       
   457 			// Flow has gone down for an expected reason
       
   458 			iLastRequestOriginator.ReplyTo(Id(), TCFDataClient::TStopped(aError).CRef());
       
   459 			// The SCPR activity will terminate so wait for the next request
       
   460 			iLastRequestErrored = EFalse;
       
   461 	    	}
       
   462 	    else
       
   463 	    	{
       
   464 			// TError message has already been sent so ignore
       
   465 	    	iLastRequestErrored = EFalse;
       
   466 			}
       
   467 	    }
       
   468     else if (iMMState == EStarted )
       
   469         {
       
   470         // Something has occured in the bearer causing the link to go down unexpectedly
       
   471         // We use the RNodeInterface version of PostMessage because
       
   472         // TDataClientGoneDown is always sent as an unsolicited message. We don't want the
       
   473         // activity Id to be overidden.
       
   474     	iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError, iTerminateAction).CRef());
       
   475 	    }
       
   476 	else if (iMMState == EStarting)
       
   477 		{
       
   478 	    if (!iLastRequestErrored)
       
   479 	    	{
       
   480 			// Unexpected termination so send TError message
       
   481 			iLastRequestOriginator.ReplyTo(Id(), TEBase::TError(TCFDataClient::TStart::Id(), aError).CRef());
       
   482 			// The SCPR activity will terminate so wait for the next request
       
   483 			iLastRequestErrored = EFalse;
       
   484 	    	}
       
   485 	    else
       
   486 	    	{
       
   487 	    	// TError message has already been sent so ignore
       
   488 	    	iLastRequestErrored = EFalse;
       
   489 	    	}
       
   490 		}
       
   491     iMMState = EStopped;
       
   492 	}
       
   493 
       
   494 void CPppLcp::PostErrorMessage(TInt aError)
       
   495 	{
       
   496 	ASSERT(aError != KErrNone);
       
   497 	// Error is always a response to an earlier received request
       
   498 	if (iLastRequestOriginator.IsOpen()) // Errors only relevant if responding to something
       
   499 		{
       
   500 		iLastRequestOriginator.ReplyTo(Id(), TEBase::TError(iLastRequest, aError).CRef());
       
   501 		}
       
   502 	}
       
   503 
       
   504 void CPppLcp::MaybePostDataClientIdle()
       
   505     {
       
   506     // Can only send DataClientIdle when the upper layer has unbound and the flow is stopped
       
   507 	if (iBinder4 == NULL && iBinder6 == NULL && !iSentIdle)
       
   508 		{
       
   509 		// TDataClientIdle is sent unsolicited to the control side
       
   510    		iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef());
       
   511 		iSentIdle = ETrue;
       
   512 		}
       
   513     }
       
   514 
       
   515 //-=========================================================
       
   516 // MFlowBinderControl methods
       
   517 //-=========================================================
       
   518 EXPORT_C MLowerControl* CPppLcp::GetControlL(const TDesC8& aProtocol)
       
   519     {
       
   520     User::LeaveIfError(iSavedError);
       
   521     MLowerControl* lowerControl = NULL;
       
   522 	if (aProtocol.CompareF(KProtocol4()) == 0  ||
       
   523 		aProtocol.CompareF(KDescIcmp) == 0)
       
   524 		{
       
   525         __FLOG(_L8("CPppLcp:\tGetLowerControlL(KProtocol4)"));
       
   526 		iBinder4 = CPppBinderIp4::NewL(this);
       
   527         lowerControl = iBinder4;
       
   528 		}
       
   529 	else
       
   530 	if (aProtocol.CompareF(KProtocol6()) == 0)
       
   531 		{
       
   532         __FLOG(_L8("CPppLcp:\tGetLowerControlL(KProtocol6)"));
       
   533         iBinder6 = CPppBinderIp6::NewL(this);
       
   534         lowerControl = iBinder6;
       
   535 		}
       
   536     return lowerControl;
       
   537     }
       
   538 
       
   539 EXPORT_C MLowerDataSender* CPppLcp::BindL(const TDesC8& aProtocol, MUpperDataReceiver* aReceiver, MUpperControl* aControl)
       
   540     {
       
   541     __FLOG_1(_L8("CPppLcp:\tBindL(%S)"), &aProtocol);
       
   542 
       
   543 	MLowerDataSender* lowerDataSender = NULL;
       
   544 
       
   545 	if (aProtocol.CompareF(KProtocol4()) == 0)
       
   546 		{
       
   547 		lowerDataSender = iBinder4->BindL(*aReceiver, *aControl);
       
   548 		}
       
   549 	else
       
   550 	if (aProtocol.CompareF(KProtocol6()) == 0)
       
   551 		{
       
   552 		lowerDataSender = iBinder6->BindL(*aReceiver, *aControl);
       
   553 		}
       
   554 
       
   555 	if (lowerDataSender)
       
   556     	{
       
   557     	// TDataClientActive is sent unsolicited to the control side
       
   558     	iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TActive().CRef());
       
   559     	}
       
   560 
       
   561 	return lowerDataSender;
       
   562     }
       
   563 
       
   564 EXPORT_C void CPppLcp::Unbind(MUpperDataReceiver* aReceiver, MUpperControl* aControl)
       
   565     {
       
   566     __FLOG(_L8("CPppLcp:\tUnbind()"));
       
   567 
       
   568 	if (iBinder4 && iBinder4->MatchesUpperControl(aControl))
       
   569 		{
       
   570         iBinder4->UnBind(*aReceiver, *aControl);
       
   571 		delete iBinder4;
       
   572 		iBinder4 = NULL;
       
   573 		}
       
   574 	else if (iBinder6 && iBinder6->MatchesUpperControl(aControl))
       
   575 		{
       
   576         iBinder6->UnBind(*aReceiver, *aControl);
       
   577 		delete iBinder6;
       
   578 		iBinder6 = NULL;
       
   579 		}
       
   580 
       
   581     MaybePostDataClientIdle();
       
   582     }
       
   583 
       
   584 EXPORT_C CSubConnectionFlowBase* CPppLcp::Flow()
       
   585 	{
       
   586 	return this;
       
   587 	}
       
   588 
       
   589 //-=========================================================
       
   590 // MUpperDataReceiver methods
       
   591 //-=========================================================
       
   592 EXPORT_C void CPppLcp::Process(RMBufChain& aData)
       
   593     {
       
   594     LinkRecv(aData);
       
   595     }
       
   596 
       
   597 //-=========================================================
       
   598 // MUpperControl methods
       
   599 //-=========================================================
       
   600 EXPORT_C void CPppLcp::StartSending()
       
   601     {
       
   602     if (iBinder4)
       
   603     	{
       
   604     	iBinder4->SendFlowOn();
       
   605     	}
       
   606     if (iBinder6)
       
   607     	{
       
   608     	iBinder6->SendFlowOn();
       
   609     	}
       
   610     }
       
   611 
       
   612 EXPORT_C void CPppLcp::Error(TInt aError)
       
   613 	{
       
   614 	if (iLastRequestOriginator.IsOpen())
       
   615 		{
       
   616 		// There is an outstanding request to complete
       
   617 		iLastRequestOriginator.ReplyTo(Id(),TEBase::TError(iLastRequest, aError).CRef());
       
   618 		iLastRequestErrored = ETrue;
       
   619 		}
       
   620 	else
       
   621 		{
       
   622 		// There is no outstanding request to complete
       
   623 		// This is a spurious error that will be ignored by
       
   624 		// the SCPR
       
   625 		__ASSERT_DEBUG(EFalse, PppPanic(EPppPanic_SpuriousError));
       
   626 		}
       
   627     iLastRequest = Messages::TNodeSignal::TMessageId();
       
   628 	}
       
   629 
       
   630 //-=========================================================
       
   631 // Custom methods
       
   632 //-=========================================================
       
   633 // provide compatability for classes using old CNifIfLink style API
       
   634 void CPppLcp::ProvisionConfigL(const ESock::RMetaExtensionContainerC& aConfigData)
       
   635 /**
       
   636 Handle ProvisionConfig messages from SCPR.
       
   637 
       
   638 Provisioning requirements:
       
   639 
       
   640 - On receipt of a ProvisionConfig message, provisioning information in the SAccessPointConfig array
       
   641   is validated, and the following structures must be present:
       
   642   	- CBCAProvision, CIPConfig, CPppLcpConfig, CPppAuthConfig
       
   643   if any are missing, then an error is saved in iSavedError (there is no response to ProvisionConfig).
       
   644 
       
   645 - on receipt of a StartFlow message:
       
   646   - if iSavedError is not KErrNone, send a Error message to SCPr
       
   647   - search SAccessPointConfig again (in RetrieveDynamicProvisionInfo()), for Agent provisioning
       
   648     information:
       
   649   	- CAgentProvisionInfo, CPppProvisionInfo
       
   650   	if any are missing, send a Error message to SCPr
       
   651 */
       
   652     {
       
   653 	// Retrieve MetaConnectionProvider provisioned information
       
   654   	iBCAProvision = static_cast<const CBCAProvision*>(
       
   655   	      aConfigData.FindExtension(STypeId::CreateSTypeId(CBCAProvision::EUid, CBCAProvision::ETypeId)));
       
   656   	iPppNcpConfig = static_cast<const CIPConfig*>(
       
   657   	      aConfigData.FindExtension(STypeId::CreateSTypeId(CIPConfig::EUid, CIPConfig::ETypeId)));
       
   658   	iPppLcpConfig = static_cast<const CPppLcpConfig*>(
       
   659   	      aConfigData.FindExtension(STypeId::CreateSTypeId(CPppLcpConfig::EUid, CPppLcpConfig::ETypeId)));
       
   660   	iPppAuthConfig  = static_cast<const CPppAuthConfig*>(
       
   661   	      aConfigData.FindExtension(STypeId::CreateSTypeId(CPppAuthConfig::EUid, CPppAuthConfig::ETypeId)));
       
   662 
       
   663     if (iBCAProvision == NULL || iPppNcpConfig == NULL || iPppLcpConfig == NULL || iPppAuthConfig == NULL)
       
   664         {
       
   665         __FLOG_4(_L8("CPppLcp:\tError: ProvisionConfigL() - PPP config incomplete: iBCAProvision %08x, iPppNcpConfig %08x, iPppLcpConfig %08x, iPppAuthConfig %08x"),
       
   666         		 iBCAProvision, iPppNcpConfig, iPppLcpConfig, iPppAuthConfig);
       
   667         User::Leave(KErrCorrupt);
       
   668         }
       
   669 
       
   670     iAccessPointConfig.Close();
       
   671 	iAccessPointConfig.Open(aConfigData);
       
   672 
       
   673 	if (!iInitialised && GetLcpConfig() && GetNcpConfig() && GetAuthConfig() && GetBCAProvision())
       
   674 		{
       
   675 		InitL();
       
   676 		iInitialised = ETrue;
       
   677 		}
       
   678     }
       
   679 
       
   680 TInt CPppLcp::RetrieveDynamicProvisionInfo()
       
   681 /**
       
   682 Retrieve Provisioning Information which becomes available at Flow start time.
       
   683 
       
   684 @return KErrNone if success, KErrCorrupt if information not available.
       
   685 */
       
   686 	{
       
   687 	// Retrieve Agent provisioned information.
       
   688 	// The only thing PPP needs from the Agent provisioned information are the credentials,
       
   689 	// whilst PPP doesn't always pursue authentication. It's ok to continue for now.
       
   690 	iAgentProvision = static_cast<const CAgentProvisionInfo*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(CAgentProvisionInfo::EUid, CAgentProvisionInfo::ETypeId)));
       
   691 #ifdef _DEBUG
       
   692 	if (iAgentProvision == NULL)
       
   693     	{
       
   694         __FLOG_0(_L8("CPppLcp:\tRetrieveDynamicProvisionInfo() - Generic agent config not found, continuing"));
       
   695     	}
       
   696 #endif
       
   697 
       
   698 	// Retrieve PPP specific Agent provisioned information
       
   699 	iPppAgentProvision = static_cast<const CPppProvisionInfo*>(
       
   700           AccessPointConfig().FindExtension(STypeId::CreateSTypeId(CPppProvisionInfo::EUid, CPppProvisionInfo::ETypeId)));
       
   701 
       
   702     if (iPppAgentProvision == NULL)
       
   703         {
       
   704         __FLOG_0(_L8("CPppLcp:\tRetrieveDynamicProvisionInfo() - PPP agent config not found"));
       
   705         return KErrCorrupt;
       
   706         }
       
   707 	return KErrNone;
       
   708 	}
       
   709 
       
   710 void CPppLcp::Stop(TInt aReason, MNifIfNotify::TAction aAction)
       
   711     {
       
   712     DoStopFlow(aReason, aAction);
       
   713     }
       
   714 
       
   715 MLowerDataSender::TSendResult CPppLcp::Send(RMBufChain& aPdu, TUint aProtocol)
       
   716     {
       
   717     return MLowerDataSender::TSendResult(iPppLink->Send(aPdu, aProtocol));
       
   718     }
       
   719 
       
   720 //
       
   721 // Upcalls from Binders
       
   722 //
       
   723 
       
   724 // BinderLinkUp() overriden by CFProtocols derived from CPppLcp
       
   725 EXPORT_C void CPppLcp::BinderLinkUp(TPppProtocol aProtocol)
       
   726 	{
       
   727 	(void)aProtocol;
       
   728 	ASSERT(aProtocol >= CPppLcp::EPppProtocolBegin && aProtocol <= CPppLcp::EPppProtocolEnd);
       
   729 	FlowUp();
       
   730 	}
       
   731 
       
   732 void CPppLcp::Progress(TInt aStage, TInt aError)
       
   733 /**
       
   734 Upcall from binders to send progress
       
   735 
       
   736 @param aProgress progress parameters
       
   737 @param aProtocol protocol.  This field is primarily for the benefit of CFProtocols that
       
   738 derive from CPppLcp, so that they can identify which binder type is issuing the progress.
       
   739 
       
   740 */
       
   741 	{
       
   742     __FLOG_2(_L8("CPppLcp:\tProgress(%d, %d)"), aStage, aError);
       
   743 	PostProgressMessage(aStage, aError);
       
   744 	}
       
   745 
       
   746 void CPppLcp::FlowUp()
       
   747     {
       
   748     __FLOG(_L8("CPppLcp:\tFlowUp()"));
       
   749 	PostDataClientStartedMessage();
       
   750     }
       
   751 
       
   752 void CPppLcp::FlowDown(TInt aError, MNifIfNotify::TAction aAction)
       
   753     {
       
   754     __FLOG_2(_L8("CPppLcp:\tFlowDown(%d, %d)"), aError, aAction);
       
   755 
       
   756 	// If ENoAction is specified, this is just an
       
   757     // informational call indicating that the link has gone
       
   758     // down briefly and is expected to go back up shortly.
       
   759     if(aAction == MNifIfNotify::ENoAction)
       
   760     	{
       
   761     	return;
       
   762     	}
       
   763     	
       
   764     if (aError == KErrNone)
       
   765         {
       
   766         //It is quite common for the fsm to pass an errorless down signal.
       
   767         aError = KErrUnknown;
       
   768         }
       
   769 
       
   770     //awaiting FsmTermination phase complete to post flow down
       
   771     iTerminateAction = aAction;
       
   772     PostFlowDownMessage(aError);
       
   773     }
       
   774 
       
   775 
       
   776 //-=========================================================
       
   777 // For CPPPAuthenticate methods - might be worth moving them elsewhere.
       
   778 //-=========================================================
       
   779 void CPppLcp::Authenticate(CPppAuthentication* aAp)
       
   780 	{
       
   781 	if(iAuthenticateDone)
       
   782 		{
       
   783 	    __FLOG(_L8("CPppLcp:\tAuthenticate(): calling CallAuthenticateComplete()"));
       
   784 		aAp->CallAuthenticateComplete(KErrNone);
       
   785 		return;
       
   786 		}
       
   787 
       
   788 	if(iAuthenticate)
       
   789     	{
       
   790     	aAp->CallAuthenticateComplete(KErrAlreadyExists);
       
   791     	return;
       
   792     	}
       
   793 
       
   794     if (iAgentProvision == NULL)
       
   795         {
       
   796         //PPP decides to authenticate, but there is no
       
   797         //agent provision structure holding the credentials.
       
   798         aAp->CallAuthenticateComplete(KErrCorrupt);
       
   799         }
       
   800 
       
   801     __FLOG(_L8("CPppLcp:\tAuthenticate(): sending Authenticate message"));
       
   802 
       
   803 	// Send Authenticate message to SCPR requesting credentials for authentication.
       
   804 	// TAuthenticate is sent unsolicited to the control side
       
   805 	iSubConnectionProvider.PostMessage(Id(), TLinkMessage::TAuthenticate().CRef());
       
   806 
       
   807     iAuthenticate = aAp;
       
   808 	}
       
   809 
       
   810 void CPppLcp::CancelAuthenticate(CPppAuthentication* aAp)
       
   811 	{
       
   812 
       
   813 	if(aAp==iAuthenticate)
       
   814 		{
       
   815 		iAuthenticate=0;
       
   816 		iLastRequestOriginator.ReplyTo(Id(), TEBase::TCancel().CRef());
       
   817 		}
       
   818 	}
       
   819 
       
   820 //-=========================================================
       
   821 // CSubConnectionFlowBase methods
       
   822 //-=========================================================
       
   823 EXPORT_C MFlowBinderControl* CPppLcp::DoGetBinderControlL()
       
   824     {
       
   825     return this;
       
   826     }
       
   827 
       
   828 // ---- PPP Specifics ----
       
   829 void CPppLcp::InitL()
       
   830 /**
       
   831 Construct the Link Protocol Object
       
   832 
       
   833 @exception leaves if could not allocate memory
       
   834 @returns none
       
   835  */
       
   836 	{
       
   837 	ASSERT(!iInitialised && GetLcpConfig() && GetNcpConfig() && GetAuthConfig() && GetBCAProvision());
       
   838 
       
   839 #ifdef ESOCK_LOGGING_ACTIVE
       
   840 	// instantiate logging object
       
   841 
       
   842 	ASSERT(iLogger == NULL);
       
   843 
       
   844 	iLogger = CPppLog::NewL();
       
   845 	iLogLevel = 1; //Set default log level
       
   846 
       
   847 	LOG( iLogger->Printf(_L("-----------------------------------------------------------------------------------------")); )
       
   848 	LOG( iLogger->Printf(_L("---- New PPP instance [0x%+08x] ------------------------------------------------------"), this); )
       
   849 	LOG( iLogger->Printf(_L("-----------------------------------------------------------------------------------------")); )
       
   850 
       
   851   	// Determine the link mode early so everyone can read it
       
   852   	iLinkMode = GetLcpConfig()->GetIfServerMode();
       
   853   	LOG(
       
   854   		if (iLinkMode == CPppLcpConfig::EPppLinkIsServer)
       
   855   			{
       
   856  			iLogger->Printf(_L("PPP running in server mode"));
       
   857   			}
       
   858   		else
       
   859   			{
       
   860   			iLogger->Printf(_L("PPP running in client mode"));
       
   861   			}
       
   862   		)
       
   863 #endif
       
   864 
       
   865 	FsmConstructL();
       
   866 
       
   867 
       
   868 	// Use HDLC as lower layer
       
   869 	iPppLink = PppLink()->PppCreateLinkL(this, KNullDesC);
       
   870 
       
   871 	if(iPppLink)
       
   872 		{
       
   873 		iContainerForDlls = CObjectConIx::NewL();
       
   874 
       
   875 		//
       
   876 		// Note: Authentication credentials (iCredentials) are initialised from SCPR
       
   877 		// provisioning information.
       
   878 		//
       
   879 
       
   880 		// Create compression control protocol object
       
   881 		iPppCcp = CPppCcp::NewL(this);
       
   882 
       
   883 		// Create authentication protocol configuration object
       
   884 		iPppAcp = CPppAcp::NewL(this);
       
   885 
       
   886 		// Create link quality checking object
       
   887 		iPppLrd = CPppLrd::NewL(this);
       
   888 		Register();
       
   889 		}
       
   890 	}
       
   891 
       
   892 void CPppLcp::CallbackGrantedAndAuthenticated()
       
   893 /**
       
   894 To be called when the authentication (if any) has been completed successfully.
       
   895 If there's no authentication at all, this should be called at the
       
   896 point where the authentication phase would otherwise be.
       
   897 
       
   898 If the other end has agreed to our request for callback, then this causes NETDIAL
       
   899 to be notified that it's "all systems go" for callback.
       
   900 
       
   901 If the other end has not confirmed accepted our request for callback, or if we haven't asked,
       
   902 then this does nothing.
       
   903 */
       
   904 	{
       
   905 	if (! iCallbackRequestGranted)
       
   906 		return;
       
   907 
       
   908 	iCallbackRequestGranted = EFalse;	// do this once only (cheat)
       
   909 
       
   910 	//
       
   911 	// The following used to be Notification(ENifToAgentEventTypePPPCallbackGranted), but
       
   912 	// has been converted to a progress to avoid having to define a special Flow to SCPR
       
   913 	// Notification() message.
       
   914 	PostProgressMessage(EPppProgressCallbackGranted, KErrNone);
       
   915 	}
       
   916 
       
   917 
       
   918 static const TInt KMaxCallbackRequestInfo = 256;
       
   919 
       
   920 class CallbackAction
       
   921 	{
       
   922 public:
       
   923 	static INLINE TBool	IsInfoFieldRequired( TCallbackAction aCallbackAction );
       
   924 	static INLINE TCallbackIETFRequestType  IETFRequestType( TCallbackAction aCallbackAction );
       
   925 	static INLINE TBool IsMSCBCP( TCallbackAction aCallbackAction );
       
   926 	static INLINE TMSCBCPAction MSCBCPAction( const TCallbackAction aAction );
       
   927 	};
       
   928 
       
   929 
       
   930 INLINE TMSCBCPAction CallbackAction::MSCBCPAction( const TCallbackAction aAction )
       
   931 	{
       
   932 	__ASSERT_DEBUG( aAction == ECallbackActionMSCBCPRequireClientSpecifiedNumber
       
   933 						|| aAction == ECallbackActionMSCBCPAcceptServerSpecifiedNumber
       
   934 						|| aAction == ECallbackActionMSCBCPOverrideServerSpecifiedNumber,
       
   935 					PppPanic(EPppPanic_PPPInvalidCallback) );
       
   936 
       
   937 	return (TMSCBCPAction) aAction;
       
   938 	}
       
   939 
       
   940 
       
   941 TBool CallbackAction::IsInfoFieldRequired( TCallbackAction aCallbackAction )
       
   942 	{
       
   943 	switch (aCallbackAction)
       
   944 		{
       
   945 	case ECallbackActionIETFType0:
       
   946 		return EFalse;
       
   947 	case ECallbackActionIETFType1:
       
   948 		return ETrue;
       
   949 	case ECallbackActionIETFType2:
       
   950 		return ETrue;
       
   951 	case ECallbackActionIETFType3:
       
   952 		return ETrue;
       
   953 	case ECallbackActionIETFType4:
       
   954 		return ETrue;
       
   955 	case ECallbackActionIETFType5:
       
   956 		return ETrue;
       
   957 	case ECallbackActionMSCBCPRequireClientSpecifiedNumber:
       
   958 		return ETrue;
       
   959 	case ECallbackActionMSCBCPAcceptServerSpecifiedNumber:
       
   960 		return EFalse;
       
   961 	case ECallbackActionMSCBCPOverrideServerSpecifiedNumber:
       
   962 		return ETrue;
       
   963 	default:
       
   964 		__ASSERT_DEBUG(EFalse, PppPanic(EPppPanic_PPPInvalidCallback));
       
   965 		return EFalse;
       
   966 		}
       
   967 	}
       
   968 
       
   969 
       
   970 inline TBool CallbackAction::IsMSCBCP( TCallbackAction aCallbackAction )
       
   971 	{
       
   972 	return int(aCallbackAction) > KMinValueForMSCallBackCode;	// MS codes are >1000
       
   973 	}
       
   974 
       
   975 
       
   976 TCallbackIETFRequestType CallbackAction::IETFRequestType( TCallbackAction aCallbackAction )
       
   977 	{
       
   978 	return CallbackAction::IsMSCBCP( aCallbackAction )
       
   979 				? ECallbackIETFRequestTypeMSCBCP
       
   980 				: TCallbackIETFRequestType( aCallbackAction );
       
   981 	}
       
   982 
       
   983 
       
   984 
       
   985 TBool CPppLcp::QueryExternalIPConfiguration()
       
   986 /**
       
   987 Returns the external IP configuration flag.
       
   988 @return	External IP configuration flag value. */
       
   989 	{
       
   990 	return iDoExternalIPConfiguration;
       
   991 	}
       
   992 
       
   993 void CPppLcp::InitCallbackInfoL()
       
   994 	{
       
   995 	if ( !GetLcpConfig()->GetIfCallbackEnabled() )
       
   996     	{
       
   997     	return;
       
   998     	}
       
   999 	if ( GetPppAgentConfig()->IsDialIn() )
       
  1000     	{
       
  1001     	return;
       
  1002     	}
       
  1003 
       
  1004 	iCallbackEnabled = ETrue;
       
  1005 	iCallbackAction = TCallbackAction(GetLcpConfig()->GetIfCallbackType());
       
  1006 	iCallbackIETFRequestType = CallbackAction::IETFRequestType( iCallbackAction );
       
  1007 	NewCallbackRequestInfoL( iCallbackIETFRequestType );
       
  1008 
       
  1009 	if ( CallbackAction::IsMSCBCP( iCallbackAction ) )
       
  1010 		{
       
  1011 		if ( CallbackAction::IsInfoFieldRequired( iCallbackAction ) )
       
  1012 			{
       
  1013 			// Get the info field from the NETDIAL database, for the benefit of MS-CBCP
       
  1014 			GetCallbackInfoL();	// sets iCallbackInfo
       
  1015 			}
       
  1016 		iPppMsCbcp = PppNcpMsCbcpFactory::NewL(	this,				// CPppLcp* aLcp,
       
  1017 												CallbackAction::MSCBCPAction( iCallbackAction ),	// TMSCBCPAction aAction,
       
  1018 												iCallbackInfo,		// TUint8*  aCallbackInfo,
       
  1019 												iCallbackInfoLen ); // TInt aCallbackInfoLen
       
  1020 		}
       
  1021 	}
       
  1022 
       
  1023 
       
  1024 void CPppLcp::GetCallbackInfoL()
       
  1025 /**
       
  1026 Get the CallbackInfo field from the NETDIAL database
       
  1027 Allocates a buffer for it, and (if successful)
       
  1028 sets iCallbackInfo to point at the buffer allocated.
       
  1029 
       
  1030 @post iCallbackInfo, iCallbackInfoLen are set
       
  1031 */
       
  1032 	{
       
  1033 	if ( iCallbackInfo )	// already done it
       
  1034         {
       
  1035         return;
       
  1036         }
       
  1037   	TUint8*  p = new (ELeave) TUint8[ KMaxCallbackRequestInfo ];
       
  1038   	TPtr8 tptr( p, KMaxCallbackRequestInfo );
       
  1039     tptr.Copy(GetLcpConfig()->GetIfCallbackInfo());
       
  1040   	TInt len = tptr.Length();
       
  1041 
       
  1042   	iCallbackInfo = p;
       
  1043   	iCallbackInfoLen = len;
       
  1044 	__ASSERT_DEBUG( iCallbackInfo, PppPanic(EPppPanic_PPPNoCallbackInfo) );
       
  1045 	__ASSERT_DEBUG( iCallbackInfoLen <=KMaxCallbackRequestInfo, PppPanic(EPppPanic_PPPInvalidCallback) );
       
  1046 	}
       
  1047 
       
  1048 void CPppLcp::NewCallbackRequestInfoL( TCallbackIETFRequestType aRequestType )
       
  1049 /**
       
  1050 Allocates a buffer containing a PPP callback request packet a la draft RFC.
       
  1051 
       
  1052 Format is: [ length ] [ type ] [ .. info ... ]
       
  1053 
       
  1054 @post Sets iCallbackIETFRequestPacket to point to the buffer allocated
       
  1055 
       
  1056 @param aRequestType Callback IETF request type code
       
  1057 */
       
  1058 	{
       
  1059 
       
  1060 	if ( iCallbackIETFRequestPacket )	// if buffer exists already, delete it
       
  1061 		{
       
  1062 		delete iCallbackIETFRequestPacket;
       
  1063 		iCallbackIETFRequestPacket = NULL;
       
  1064 		}
       
  1065 	TInt len;
       
  1066 	if ( aRequestType == ECallbackIETFRequestType0 || aRequestType == ECallbackIETFRequestTypeMSCBCP)
       
  1067 		{
       
  1068 		len = 0;
       
  1069 		}
       
  1070 	else
       
  1071 		{
       
  1072 		GetCallbackInfoL();	// Sets iCallbackInfo to be valid
       
  1073 		__ASSERT_DEBUG( iCallbackInfo, PppPanic(EPppPanic_PPPNoCallbackInfo) );
       
  1074 		len = iCallbackInfoLen;
       
  1075 		}
       
  1076 	__ASSERT_DEBUG( !iCallbackIETFRequestPacket, PppPanic(EPppPanic_PPPInvalidCallback) );
       
  1077 
       
  1078 	// Allocate space for the Operation byte i.e. aRequestType ( 0 - 4 )
       
  1079 	iCallbackIETFRequestPacket = new (ELeave) TUint8[ len + 1 ];
       
  1080 	// Set the length to include the Operation byte
       
  1081 	iCallbackIETFRequestPacketLen = len+1;
       
  1082 	// Set up the Operation Byte
       
  1083 	iCallbackIETFRequestPacket[0] = TUint8( aRequestType );
       
  1084 	// Append the database retrieved information field (Could be a Phone Number)
       
  1085 	// Generic code will add Callback type code and length byte later on
       
  1086 	if(len)
       
  1087 		Mem::Copy( iCallbackIETFRequestPacket +1, iCallbackInfo, len);
       
  1088 	}
       
  1089 
       
  1090 
       
  1091 void CPppLcp::PhaseAdvancesBeyondAuthenticate()
       
  1092 	{
       
  1093 	CallbackGrantedAndAuthenticated();
       
  1094 	}
       
  1095 
       
  1096 
       
  1097 TBool CPppLcp::DoesDllExist(const TDesC& aFilename)
       
  1098 /**
       
  1099 Search to see if a loadable DLL does actually exist
       
  1100 
       
  1101 @param aFilename DLL filename
       
  1102 
       
  1103 @return ETrue if the file exists
       
  1104 */
       
  1105 	{
       
  1106 	TBool RetCode = EFalse;
       
  1107 
       
  1108 
       
  1109     RLibrary lib;
       
  1110 	_LIT(KSysLibs,"\\SYSTEM\\LIBS\\");
       
  1111     if (lib.Load(aFilename, KSysLibs) == KErrNone)
       
  1112         {
       
  1113         RetCode = ETrue;
       
  1114         lib.Close();
       
  1115         }
       
  1116 
       
  1117 	return RetCode;
       
  1118 	}
       
  1119 
       
  1120 TInt CPppLcp::DoStartFlow()
       
  1121 /**
       
  1122 Start the PPP link.
       
  1123 
       
  1124 @return Error code
       
  1125 */
       
  1126 	{
       
  1127 	TInt err = KErrNone;
       
  1128 #if defined (_DEBUG)
       
  1129 	// Move logging to new log file
       
  1130 	TRAP(err, iLogger->SetLogFileNameL(GetNcpConfig()->GetPortName()));
       
  1131 	if (err!=KErrNone)
       
  1132 		{
       
  1133 		// ** DO NOT forget to enclose any LOG() macros after an 'if' within '{...}' or else
       
  1134 		// the first innocent source line after the LOG() statement will be swallowed
       
  1135 		// by the 'if' when LOG() is empty !!
       
  1136 		LOG( iLogger->Printf(_L("Could not change log file name for this instance of PPP [0x%+08x]"), this); )
       
  1137 		}
       
  1138 
       
  1139 	if (GetLcpConfig()->GetISPName().Ptr())
       
  1140 		{
       
  1141 		_LIT(KLine64, "---------------------------------------------------------------");
       
  1142 		LOG( iLogger->Printf(KLine64); )  ;
       
  1143 		LOG( iLogger->Printf(_L("Calling ISP '%S' using modem on %S"), GetLcpConfig()->GetISPName().Ptr(), GetNcpConfig()->GetPortName().Ptr()); ) ;
       
  1144 		LOG( iLogger->Printf(KLine64); ) ;
       
  1145 		}
       
  1146 #endif
       
  1147 
       
  1148 	err = RetrieveDynamicProvisionInfo();
       
  1149 	if (err != KErrNone)
       
  1150 		{
       
  1151 		return err;
       
  1152 		}
       
  1153 
       
  1154     iDoLcpExts=GetLcpConfig()->GetEnableLcpExtensions();
       
  1155 
       
  1156 	// Are we doing external IP configuration (MobileIP)?
       
  1157 	TRAPD(res, PppLink()->StartL();)
       
  1158 
       
  1159 	//Are we doing CCP ?
       
  1160 	if (!GetLcpConfig()->GetEnableSwComp())
       
  1161 		{
       
  1162 		//Deregister CCP
       
  1163 		if(iPppCcp)
       
  1164 			iPppCcp->RemoveRegistration();
       
  1165 		}
       
  1166 
       
  1167 	// Configure the FSM to never time out while connecting if we're a server
       
  1168 	ConnectionPersist(PppLinkMode() == CPppLcpConfig::EPppLinkIsServer);
       
  1169 
       
  1170 	return res;
       
  1171 	}
       
  1172 
       
  1173 void CPppLcp::DoStopFlow(TInt aReason, MNifIfNotify::TAction aAction)
       
  1174 /**
       
  1175 Cleanly stop the LCP link and notify the NIF.
       
  1176 If aReason == KErrConnectionTerminated signal Authoritative stop: there is no graceful
       
  1177 termination: PPP signals CNifAgentRef::LinkLayerDown to Nifman, which results in PPP deletion.
       
  1178 
       
  1179 @param aReason The reason the link is going down
       
  1180 @param aAction The action to take once the link is down
       
  1181 */
       
  1182 	{
       
  1183  	LOG( iLogger->Printf(_L("CPppLcp::Stop: Administrative Close of PPP. aReason [%d], aAction [%d]"),aReason, aAction); )
       
  1184  	iFsmTerminationCauseError = aReason;
       
  1185 
       
  1186  	// If it's an Authoritative Stop (KErrConnectionTerminated),
       
  1187  	// we shut down as quickly as possible, with no concern for
       
  1188  	// graceful termination. The assumption is that other networking components do the same, i.e.
       
  1189  	// they do not expect us to shut down gracefully.
       
  1190  	// We do not go through RFC-compliant PPP Termination sequence, because shutting down and releasing resources
       
  1191  	// has higher priority than negotiationg with the peer.
       
  1192 	if(KErrConnectionTerminated != aReason)  // Normal stop
       
  1193 		{
       
  1194 		if(iTerminateRequestEnabled) // Fully RFC1661 compliant shutdown, as opposed to "legacy" shutdown.
       
  1195 		                             // Once the "legacy" shutdown (provided for back-compatibility) is removed,
       
  1196 		                             // the check for TerminateRequestEnabled may be safely removed as well.
       
  1197 			{
       
  1198 			FsmLayerDown(aReason);
       
  1199  			TerminateLink(aAction, aReason);
       
  1200  			return;
       
  1201 			}
       
  1202 		else // "Legacy" shutdown sequence.
       
  1203 		     // PPP terminates immediately, after making a "best-effort" attempt to send 1 LCP TerminateRequest.
       
  1204 		     // Once this legacy behaviour is not required any more, this section of code may be safely removed.
       
  1205 			{
       
  1206 			TerminateLink(aAction, aReason); // "Best-effort" attempt to send TerminateRequest.
       
  1207 			// Proceed to "Authoritative" shutdown. This may result in TerminateRequest being cancelled.
       
  1208 			}
       
  1209 		}
       
  1210 
       
  1211 	// This is the "Authoritative" shutdown sequence. If we are terminating gracefully, we will not get here.
       
  1212 	// Inform Nifman that we are ready to be cleaned-up. We do not do full clean-up here,
       
  1213  	// because this is done anyway in destructors, which will be invoked once Nifman tells PPP to delete itself.
       
  1214  	// At this point we want to unblock Nifman as quickly as possible, to allow it to proceed with the rest
       
  1215  	// of the Authoritative shutdown sequence.
       
  1216 	PppLink()->Stop(aReason); // Make sure PPP does not use the Link after telling nifman that the NIF is finished.
       
  1217 
       
  1218  	// We need to inform Nifman from here only if it is authoritative shutdown.
       
  1219  	// In other cases, FSM goes through state transitions on shutdown, which result
       
  1220  	// in FsmTerminationPhaseComplete to be called, and notify the Nifman.
       
  1221  	if(KErrConnectionTerminated == aReason)
       
  1222  		{
       
  1223  		// Tell Nifman that PPP is finished. After the Agent finishes (terminates the connection, air link, etc), Nifman
       
  1224  		// closes the NIF, which results in PPP deletion. The call to delete PPP originates in Nifman, implemented as
       
  1225  		// asynchronous callback. This call would invoke the destructors, which do the actual cleanup in the NIF.
       
  1226  	 	//iNotify->LinkLayerDown(aReason, aAction); REMEK: DO SOMETHING HERE - TALK TO NADEEM,
       
  1227  	 	                                          //the following line has been added as a replacement of this line.
       
  1228 
       
  1229  		PostProgressMessage(EPppProgressLinkDown, aReason);
       
  1230  	 	PostFlowDownMessage(aReason);
       
  1231  		}
       
  1232 	}
       
  1233 
       
  1234 //
       
  1235 // Protocols Manager
       
  1236 //
       
  1237 
       
  1238 TInt CPppLcp::PppOpen()
       
  1239 /**
       
  1240 Called by an upper layer when it is started.
       
  1241 
       
  1242 @return Error code
       
  1243 */
       
  1244 	{
       
  1245 
       
  1246 	LOG( iLogger->Printf(_L("PPPOpen - iOpenCount=%d\n"),iOpenCount); )
       
  1247 	if (iOpenCount++>0)
       
  1248 		return KErrNone;
       
  1249 
       
  1250 	return FsmOpen();
       
  1251 	}
       
  1252 
       
  1253 void CPppLcp::PppClose(TInt aReason)
       
  1254 /**
       
  1255 Called by an upper layer when it is finished.
       
  1256 
       
  1257 @param aReason The reason the protocol is finished
       
  1258 */
       
  1259 	{
       
  1260 	LOG( iLogger->Printf(_L("PPPClose - iOpenCount=%d\r\n"),iOpenCount); )
       
  1261 	if (--iOpenCount>0)
       
  1262 		{
       
  1263 		if (AllNcpsUp()) //This will need to happen when one ncp goes up but the other does not go up
       
  1264 			{
       
  1265 			FlowUp();
       
  1266 			}
       
  1267 		return;
       
  1268 		}
       
  1269 	FsmClose(aReason);
       
  1270 	iNcpUpCount = 0;
       
  1271 	}
       
  1272 
       
  1273 void CPppLcp::RegisterRecvr(MPppRecvr* aRecvr)
       
  1274 /**
       
  1275 Register an object that is interested in receiving certain packets.
       
  1276 The receiver object knows the protocol number it is interested in.
       
  1277 
       
  1278 @param aRecvr Object to receive packets
       
  1279 */
       
  1280 	{
       
  1281 	iRecvrList.AddLast(*aRecvr);
       
  1282 	if (aRecvr->iPppId==KPppIdLcp)
       
  1283 		return;
       
  1284 
       
  1285 	if (iPhase>=aRecvr->iActivePhase)
       
  1286 			aRecvr->LowerLayerUp();
       
  1287 
       
  1288 	else
       
  1289 		aRecvr->LowerLayerDown(KErrNone);
       
  1290 	}
       
  1291 
       
  1292 void CPppLcp::ReregisterRecvr(MPppRecvr* aRecvr)
       
  1293 /**
       
  1294 Reregister an object that is receiving certain packets.
       
  1295 The receiver object knows the protocol number it is interested in.
       
  1296 
       
  1297 @param aRecvr Object registered to receive packets
       
  1298 */
       
  1299 	{
       
  1300 	aRecvr->Deque();
       
  1301 	RegisterRecvr(aRecvr);
       
  1302 	}
       
  1303 
       
  1304 void CPppLcp::DeregisterRecvr(MPppRecvr* aRecvr)
       
  1305 /**
       
  1306 Unregister an object that is no longer interested in receiving certain
       
  1307 packets.
       
  1308 
       
  1309 @param aRecvr Object registered to receive packets
       
  1310 */
       
  1311 	{
       
  1312 	aRecvr->Deque();
       
  1313 	}
       
  1314 
       
  1315 //
       
  1316 // PPP Upcalls from Link
       
  1317 //
       
  1318 
       
  1319 void CPppLcp::LinkRecv(RMBufChain& aPacket)
       
  1320 /**
       
  1321 Called by the link layer for each new PPP packet received.
       
  1322 Search registered Recvr list and deliver to all recipients.
       
  1323 
       
  1324 @param aPacket MBuf chain containing received packet
       
  1325 */
       
  1326 	{
       
  1327 	MPppRecvr* rcvr;
       
  1328 
       
  1329 	RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(aPacket);
       
  1330 	TUint prot = TPppAddr::Cast(info->iDstAddr).GetProtocol();
       
  1331 
       
  1332    //
       
  1333    // For Van Jacobson compression have to tell NCPIP if a CRC error
       
  1334    // occurred, may as well tell all the protocols!!
       
  1335    //
       
  1336    const TBool CrcError = TPppAddr::Cast(info->iDstAddr).CRCError();
       
  1337 
       
  1338 	TDblQueIter<MPppRecvr> iter(iRecvrList);
       
  1339 	while (rcvr = iter++, rcvr!=NULL)
       
  1340 		{
       
  1341 		if (CrcError)
       
  1342 			{
       
  1343 			rcvr->FrameError();
       
  1344 			continue;
       
  1345 			}
       
  1346 
       
  1347 		if (prot==rcvr->iPppId)
       
  1348 			{
       
  1349 			if (iPhase>=rcvr->iActivePhase)
       
  1350 				{
       
  1351 				rcvr->RecvFrame(aPacket);
       
  1352 				return;
       
  1353 				}
       
  1354 			else
       
  1355 				{
       
  1356 				// Protocol is known, but not available so
       
  1357 				// silent discard instead of reject
       
  1358 				aPacket.Free();
       
  1359 				}
       
  1360 			}
       
  1361 		}
       
  1362 
       
  1363    if (CrcError)
       
  1364       {
       
  1365       //
       
  1366       // Have told everyone now so throw away the frame
       
  1367       //
       
  1368 		aPacket.Free();
       
  1369       }
       
  1370 
       
  1371 
       
  1372 	if (!aPacket.IsEmpty())
       
  1373 		{
       
  1374 		// Unrecognised protocol
       
  1375 		// This line was commented out and consequently NBCF requests were not
       
  1376 		// being rejected.
       
  1377 
       
  1378 
       
  1379  		// Cisco Router fix
       
  1380  		// There is a defect in some Cisco routers where they will send
       
  1381  		// an authentication request before they have sent an LCP Config-Ack
       
  1382  		// So if we are in the Ack-Sent state and we get an authentication request
       
  1383  		// - i.e. CHAP (0xC223) or PAP (0xC023)) - then silently discard the packet
       
  1384  		// rather than sending a Protocol reject
       
  1385 
       
  1386  		if ((iPhase == EPppPhaseEstablish) &&
       
  1387  			(FsmState() == EPppFsmAckSent) &&
       
  1388  			((prot == KPppIdChap) || (prot == KPppIdPap)))
       
  1389  			{
       
  1390  			; // don't send a protocol reject
       
  1391  			LOG( iLogger->Printf(_L("CHAP / PAP Authenticate request received before entering the AUTHENTICATE phase: silently discarding packet\n")); )
       
  1392  			}
       
  1393  		else
       
  1394  			FsmRejectPacket(aPacket, KPppLcpProtocolReject);
       
  1395 
       
  1396 		aPacket.Free();
       
  1397 		}
       
  1398 	}
       
  1399 
       
  1400 void CPppLcp::LinkLayerUp()
       
  1401 /**
       
  1402 Called from the lower layer when it becomes ready.
       
  1403 */
       
  1404 	{
       
  1405 	LOG( iLogger->Printf(_L("Link Layer Up")); )
       
  1406 	MPppRecvr* rcvr = this;
       
  1407 	rcvr->LowerLayerUp();
       
  1408 //	PppOpen();
       
  1409 	}
       
  1410 
       
  1411 void CPppLcp::LinkLayerDown(TInt aStatus)
       
  1412 /**
       
  1413 Called from the lower layer when it finishes shutting down.
       
  1414 
       
  1415 @param aStatus Error code indicating the reason the link is going down
       
  1416 */
       
  1417 	{
       
  1418 	// Note on errors:
       
  1419 	// Link can be down due to 1 of 2 causes: Comms failure of some sort, OR closing the link
       
  1420 	// by LCP. In the first case, we should get the Comms error from the link in aStatus.
       
  1421 	// In the second case,we have our own error describing why LCP is shutting down the link.
       
  1422 
       
  1423 	if(KErrNone == iError) // Link reported failure. We didn't ask it to be closed
       
  1424 		{
       
  1425 		if(KErrNone == aStatus) // We have no error to work with!
       
  1426 			{
       
  1427 			// We absolutely must signal an error, otherwise Nifman will
       
  1428 			// ignore NIF's notification in certain states (e.g. before KLinkLayerUp).
       
  1429 			// This results in the interface and its ESock clients being stuck.
       
  1430 			//
       
  1431 			// After the first (outgoing) stage of callback, however, signalling EPppProgressLinkDown
       
  1432 			// with an error (in FsmTerminationPhaseComplete()) incorrectly triggers Nifman to perform
       
  1433 			// a connection retry with the next preference.  Passing KErrNone in this particular
       
  1434 			// circumstance is okay.
       
  1435 			//
       
  1436 			if (iTerminateAction != MNifIfNotify::ECallBack)
       
  1437 				{
       
  1438 				iError = KErrUnknown;
       
  1439 				}
       
  1440 			}
       
  1441 		else
       
  1442 			{
       
  1443 			iError = aStatus; // Report link error as PPP error.
       
  1444 			}
       
  1445 		}
       
  1446 	// Else: we have an error code already. Most likely, as result of closing the link.
       
  1447 
       
  1448 	LOG( iLogger->Printf(_L("Link Layer Down reason %d\n"), aStatus); )
       
  1449 	MPppRecvr* rcvr = this;
       
  1450 	rcvr->LowerLayerDown(aStatus);
       
  1451 	}
       
  1452 
       
  1453 
       
  1454 void CPppLcp::LinkFlowOn()
       
  1455 /**
       
  1456 Link advisory flow on signal.
       
  1457 */
       
  1458 	{
       
  1459 	MPppRecvr* rcvr;
       
  1460 	TDblQueIter<MPppRecvr> iter(iRecvrList);
       
  1461 	while (rcvr = iter++, rcvr!=NULL)
       
  1462 		rcvr->FlowOn();
       
  1463 	}
       
  1464 
       
  1465 
       
  1466 void CPppLcp::PhaseAdvance(TPppPhase aNewPhase)
       
  1467 /**
       
  1468 Switch to the next PPP operation phase.
       
  1469 When the PPP phase is advanced, protocols may have reached
       
  1470 their active phase and so have to be bound in to the
       
  1471 main data path and signalled active.
       
  1472 
       
  1473 @param aNewPhase Phase just entered
       
  1474 */
       
  1475 	{
       
  1476 	TPppPhase oldphase = iPhase;
       
  1477 	iPhase = aNewPhase;
       
  1478 	LOG( iLogger->DumpPhase(oldphase, aNewPhase); )
       
  1479 	if (oldphase==aNewPhase)
       
  1480 		return;
       
  1481 	TBool skip = ETrue;
       
  1482 
       
  1483 	if (!iRecvrList.IsEmpty())
       
  1484 		{
       
  1485 		MPppRecvr* rcvr;
       
  1486 		TDblQueIter<MPppRecvr> iter(iRecvrList);
       
  1487 		while (rcvr=iter++, rcvr!=NULL)
       
  1488 			{
       
  1489 			if (rcvr->iPppId==KPppIdLcp)
       
  1490 				continue;
       
  1491 			if (aNewPhase==rcvr->iActivePhase)
       
  1492 				{
       
  1493 				skip = EFalse;
       
  1494 
       
  1495 				rcvr->LowerLayerUp();
       
  1496 
       
  1497 				}
       
  1498 			else if (oldphase<rcvr->iActivePhase && aNewPhase>rcvr->iActivePhase)
       
  1499 				rcvr->LowerLayerUp();
       
  1500 			}
       
  1501 		}
       
  1502 	if (skip && aNewPhase>EPppPhaseEstablish && aNewPhase<EPppPhaseNetwork)
       
  1503 		PhaseComplete();
       
  1504 	}
       
  1505 
       
  1506 void CPppLcp::TerminateLink(MNifIfNotify::TAction aAction, TInt aError)
       
  1507 /**
       
  1508 Cleanly take down the LCP (and therefore PPP) link.
       
  1509 
       
  1510 @param aAction The action to take after the link terminates
       
  1511 @param aError The reason the link is going down
       
  1512 */
       
  1513 {
       
  1514 	iError = aError;
       
  1515 	iTerminateAction = aAction;
       
  1516 	LOG( iLogger->Printf(_L("TerminateLink due to error %d"), aError); )
       
  1517 	MPppFsm::TerminateLink();
       
  1518 	iGotCallbackInfo = EFalse;
       
  1519 }
       
  1520 
       
  1521 void CPppLcp::PhaseRetard(TPppPhase aNewPhase, TInt aReason)
       
  1522 /**
       
  1523 Return to a previous PPP operation phase.
       
  1524 When the PPP phase is retarded, active protocols may no
       
  1525 longer be in their active phase and so have to be unbound
       
  1526 from the main data path and signalled inactive.
       
  1527 
       
  1528 @param aNewPhase Phase just entered
       
  1529 @param aReason Error code indicating the reason we are changing phases
       
  1530 */
       
  1531 	{
       
  1532 	LOG( iLogger->Printf(_L("PhaseRetard, reason[%d]"), aReason); )
       
  1533 	if (aReason==KErrCommsLineFail && FsmIsThisLayerOpen())		// going to do reconnection
       
  1534 		iGotCallbackInfo=EFalse;
       
  1535 
       
  1536 	TPppPhase oldphase = iPhase;
       
  1537 	iPhase = aNewPhase;
       
  1538 	LOG( iLogger->DumpPhase(oldphase, aNewPhase); )
       
  1539 	if (oldphase==aNewPhase)
       
  1540 		return;
       
  1541 
       
  1542 	// Terminate the link from here if and only if it is NCP failure of some sort
       
  1543 	switch(aReason)
       
  1544 		{
       
  1545 		case KErrIfAuthenticationFailure:
       
  1546 		case KErrIfAuthNotSecure:
       
  1547 		case KErrIfAccountDisabled:
       
  1548 		case KErrIfRestrictedLogonHours:
       
  1549 		case KErrIfPasswdExpired:
       
  1550 		case KErrIfNoDialInPermission:
       
  1551 		case KErrIfChangingPassword:
       
  1552 		case KErrIfCallbackNotAcceptable:
       
  1553 		case KErrIfDNSNotFound:
       
  1554 			TerminateLink(MNifIfNotify::EDisconnect, aReason);
       
  1555 			Error(aReason);
       
  1556 		default:
       
  1557 			break;
       
  1558 		}
       
  1559 
       
  1560 
       
  1561 	if (!iRecvrList.IsEmpty())
       
  1562 		{
       
  1563 		MPppRecvr* rcvr;
       
  1564 		TDblQueIter<MPppRecvr> iter(iRecvrList);
       
  1565 		while (rcvr=iter++, rcvr!=NULL)
       
  1566 			{
       
  1567 			if (rcvr->iPppId==KPppIdLcp)
       
  1568 				continue;
       
  1569 
       
  1570 			if (/*oldphase>=rcvr->iActivePhase &&*/ aNewPhase<rcvr->iActivePhase/* || aReason!=KErrNone*/)
       
  1571 				rcvr->LowerLayerDown(aReason);
       
  1572 			}
       
  1573 		}
       
  1574    	}
       
  1575 
       
  1576 
       
  1577 void CPppLcp::PhaseComplete()
       
  1578 /**
       
  1579 Advance to the next PPP phase after successfully completing the current phase.
       
  1580 */
       
  1581 	{
       
  1582 	switch (iPhase)
       
  1583 		{
       
  1584 	case EPppPhaseTerminate:
       
  1585 		break;
       
  1586 	case EPppPhaseEstablish:
       
  1587 		PhaseAdvance(EPppPhaseEarlyCallback);
       
  1588 		break;
       
  1589 	case EPppPhaseEarlyCallback:
       
  1590 		PhaseAdvance(EPppPhaseAuthenticate);
       
  1591 		break;
       
  1592 	case EPppPhaseAuthenticate:
       
  1593 		//PhaseAdvancesBeyondAuthenticate();
       
  1594 		PhaseAdvance(EPppPhaseLateCallback);
       
  1595 		break;
       
  1596 	case EPppPhaseLateCallback:
       
  1597 		if (!iCallbackEnabled)
       
  1598 			{
       
  1599 			PhaseAdvance(EPppPhaseNetwork);
       
  1600 			}
       
  1601 		break;
       
  1602 	case EPppPhaseNetwork:
       
  1603 		break;
       
  1604 	default:
       
  1605 		break;
       
  1606 		}
       
  1607 	}
       
  1608 
       
  1609 void CPppLcp::PhaseAborted(TInt aStatus)
       
  1610 /**
       
  1611 Return to a previous PPP phase after ending the current phase.
       
  1612 
       
  1613 @param aStatus Error code indicating the reason we are ending the phase
       
  1614 */
       
  1615 	{
       
  1616 	switch (iPhase)
       
  1617 		{
       
  1618 	case EPppPhaseNetwork:
       
  1619 		{
       
  1620 		// NCP failer only translates to total failure
       
  1621 		// if there are no more live NCPs
       
  1622 		TInt nets=0;
       
  1623 		MPppRecvr* rcvr;
       
  1624 		TDblQueIter<MPppRecvr> iter(iRecvrList);
       
  1625 		while (rcvr=iter++, rcvr!=NULL)
       
  1626 			{
       
  1627 			if (rcvr->iActivePhase==EPppPhaseNetwork && rcvr->iPppAbortCode==KErrNone)
       
  1628 				++nets;
       
  1629 			}
       
  1630 		if (nets>0)
       
  1631 			break;
       
  1632 		// else fall through...
       
  1633 		}
       
  1634 	case EPppPhaseTerminate:
       
  1635 	case EPppPhaseEstablish:
       
  1636 	case EPppPhaseEarlyCallback:
       
  1637 	case EPppPhaseAuthenticate:
       
  1638 	case EPppPhaseLateCallback:
       
  1639 		PhaseRetard(EPppPhaseTerminate, aStatus);
       
  1640 		break;
       
  1641 	default:
       
  1642 		break;
       
  1643 		}
       
  1644 	}
       
  1645 
       
  1646 //
       
  1647 // PPP Upcalls from FSM
       
  1648 //
       
  1649 
       
  1650 EXPORT_C TInt CPppLcp::FsmLayerStarted()
       
  1651 /**
       
  1652 Open the layer below.
       
  1653 Upcall from the FSM.
       
  1654 
       
  1655 @return Error code
       
  1656 */
       
  1657 	{
       
  1658 	TRAPD(err, iPppLink->OpenL());
       
  1659 	if (err==KErrNone)
       
  1660 		PhaseAdvance(EPppPhaseEstablish);
       
  1661 	return err;
       
  1662 	}
       
  1663 
       
  1664 EXPORT_C void CPppLcp::FsmLayerFinished(TInt aReason)
       
  1665 /**
       
  1666 Close the layer below.
       
  1667 Upcall from the FSM.
       
  1668 
       
  1669 @param aReason Error code indicating the reason we are finished
       
  1670 */
       
  1671 	{
       
  1672 	LOG( iLogger->Printf(_L("CPppLcp::FsmLayerFinished aReason %d"), aReason); )
       
  1673 	iError = aReason;
       
  1674 	iPppLink->Close();
       
  1675 	//PhaseAborted(aReason<KErrNone ? aReason : KErrTimedOut); PRR 15/4/98
       
  1676 	PhaseAborted(aReason); // PRR 15/4/98
       
  1677 
       
  1678 	if (aReason == KErrCommsLineFail)
       
  1679 		{
       
  1680 		LinkLayerDown(aReason);
       
  1681 		}
       
  1682 	}
       
  1683 
       
  1684 EXPORT_C void CPppLcp::FsmTerminationPhaseComplete()
       
  1685 /**
       
  1686 Called when the FSM has stopped.
       
  1687 Upcall from the FSM.
       
  1688 */
       
  1689 	{
       
  1690 	LOG( iLogger->Printf(_L("CPppLcp::FsmTerminationPhaseComplete iError[%d]"), iError); )
       
  1691  	PostProgressMessage(EPppProgressLinkDown, iError);
       
  1692 
       
  1693   	if (iTerminateAction == MNifIfNotify::EDisconnect)
       
  1694   		{
       
  1695   		// Tell SCPR that PPP is finished. After the Agent finishes (terminates the connection, air link, etc), Nifman
       
  1696    		// closes the NIF, which results in PPP deletion. The call to delete PPP originates in Nifman, implemented as
       
  1697    		// asynchronous callback. This call would invoke the destructors, which do the actual cleanup in the NIF.
       
  1698 		PostFlowDownMessage(iError);
       
  1699   		}
       
  1700   	else if (iTerminateAction == MNifIfNotify::ECallBack)
       
  1701   		{
       
  1702   		// Action is not EDisconnect: this may not necessarily trigger NIF deletion - Nifman may try to restart the link.
       
  1703         iLastRequestOriginator.ReplyTo(Id(), TPPPMessage::TPppLinkExpectingCallback().CRef());
       
  1704 
       
  1705 		// After the first (outgoing) stage of callback, iTerminateAction contains ECallback.  If the
       
  1706 		// connection comes up correctly and is subsequently terminated from "below" (i.e. from HDLC
       
  1707 		// calling CPppLcp::LinkLayerDown() rather than from "above" (via CPppLcp::Stop() and TerminateLink()),
       
  1708 		// then iTerminateAction remains set to ECallback.  As a result, at the end of the call we end
       
  1709 		// up incorrectly signalling Nifman with LinkLayerDown(ECallback) which causes Nifman to wrongly
       
  1710 		// perform the ECallback actions rather than the EDisconnect actions (which means issuing a
       
  1711 		// Connect() to the Agent which subsequently goes wrong).
       
  1712 		iTerminateAction = MNifIfNotify::EDisconnect;
       
  1713 		}
       
  1714   	else
       
  1715   	    {
       
  1716   	    // It is believed that EReconnect does not get set into iTerminateStatus
       
  1717   	    // and therefore iTerminateAction should only ever be the ENoAction value
       
  1718   	    ASSERT(iTerminateAction == MNifIfNotify::ENoAction);
       
  1719   	    PostFlowDownMessage(KErrNone);
       
  1720   	    }
       
  1721 
       
  1722 	iCallbackEnabled = EFalse;
       
  1723 	iGotCallbackInfo = EFalse;
       
  1724 	PhaseAdvance(EPppPhaseTerminate);
       
  1725 	PppNcpMsCbcpFactory::Delete( iPppMsCbcp );
       
  1726 	iPppMsCbcp = NULL;
       
  1727 	}
       
  1728 
       
  1729 EXPORT_C void CPppLcp::FsmLayerUp()
       
  1730 /**
       
  1731 Signal up event to next layer above
       
  1732 Upcall from the FSM.
       
  1733 */
       
  1734 	{
       
  1735 	ExtOptNegotiationComplete();
       
  1736 	PhaseComplete();
       
  1737 	}
       
  1738 
       
  1739 EXPORT_C void CPppLcp::FsmLayerDown(TInt aReason)
       
  1740 /**
       
  1741 Signal down event to next layer above
       
  1742 Upcall from the FSM.
       
  1743 
       
  1744 @param aReason Error code indicating the reason the layer is going down
       
  1745 */
       
  1746 	{
       
  1747 	ExtOptNegotiationAborted();
       
  1748 	if(aReason!=KErrNone && iPhase==EPppPhaseEstablish)
       
  1749 		iPhase=EPppPhaseTerminate;
       
  1750 	PhaseRetard(EPppPhaseEstablish, aReason);
       
  1751 	}
       
  1752 
       
  1753 EXPORT_C void CPppLcp::FsmFillinConfigRequestL(RPppOptionList& aRequestList)
       
  1754 /**
       
  1755 Fill in Config Request to be sent
       
  1756 
       
  1757 @param aRequestList Receives LCP option list
       
  1758 */
       
  1759 	{
       
  1760 	ExtOptNegotiationStarted();
       
  1761 	iMaxSendSize = 0;
       
  1762 
       
  1763 // Removed September 1999 , both set to zero in GetSendRecvSize()
       
  1764 //	iMaxRecvSize = 0;
       
  1765 //	iPppLink->GetSendRecvSize(iMaxSendSize, iMaxRecvSize);
       
  1766 //	iMaxRecvSize could be read from ppp.ini file
       
  1767 	// Get desired Link options
       
  1768 	if (iMaxSendSize==0)
       
  1769 		iMaxSendSize = KPppDefaultFrameSize;
       
  1770 	if (iMaxRecvSize==0)
       
  1771 		iMaxRecvSize = KPppDefaultFrameSize;
       
  1772 	else if(iMaxRecvSize != KPppDefaultFrameSize)
       
  1773 		// Only add to request if not the default
       
  1774 		aRequestList.CreateAndAddL(KPppLcpOptMaxRecvUnit, (TUint16)iMaxRecvSize);
       
  1775 
       
  1776 	// Create a new magic number
       
  1777 	iConsecMagic = 0;
       
  1778 	iRemMagicNumber = 0;
       
  1779 	if (iLocMagicNumber == 0)
       
  1780 		{
       
  1781 		NewMagicNumberL(iLocMagicNumber);
       
  1782 		}
       
  1783 	aRequestList.CreateAndAddL(KPppLcpOptMagicNumber, (TUint32)iLocMagicNumber);
       
  1784 
       
  1785 	AppendCallbackRequestL( aRequestList );
       
  1786 
       
  1787 	ExtOptFillinConfigRequestL(aRequestList);
       
  1788 	}
       
  1789 
       
  1790 EXPORT_C void CPppLcp::AppendCallbackRequestL( RPppOptionList& aRequestList )
       
  1791 /**
       
  1792 Append an LCP OPT of type "callback-request" to the given list
       
  1793 
       
  1794 @param aRequestList LCP option list to fill in
       
  1795 */
       
  1796 	{
       
  1797 	if ( ! iGotCallbackInfo )
       
  1798 		{
       
  1799 		InitCallbackInfoL();
       
  1800 		iGotCallbackInfo = ETrue;
       
  1801 		}
       
  1802 
       
  1803 	if ( ! iCallbackEnabled )
       
  1804 		return;
       
  1805 	__ASSERT_DEBUG( iCallbackIETFRequestPacket, PppPanic(EPppPanic_IETFNoCalback) );
       
  1806 	__ASSERT_DEBUG( iCallbackIETFRequestPacketLen!=0, PppPanic(EPppPanic_IETFCalbackInvalid) );
       
  1807 	aRequestList.CreateAndAddL( KPppLcpOptCallback, iCallbackIETFRequestPacket, iCallbackIETFRequestPacketLen);
       
  1808 	}
       
  1809 
       
  1810 EXPORT_C void CPppLcp::FsmCheckConfigRequest(RPppOptionList& aRequestList, RPppOptionList& aAckList, RPppOptionList& aNakList, RPppOptionList& aRejList)
       
  1811 /**
       
  1812 Check options in a received config request.
       
  1813 Each option is added to the appropriate Ack, Nak or Rej list.
       
  1814 Upcall from the FSM.
       
  1815 
       
  1816 @param aRequestList LCP options to check
       
  1817 @param aAckList Acked LCP options
       
  1818 @param aNakList Naked LCP options
       
  1819 @param aRejList Rejected LCP options
       
  1820 */
       
  1821 	{
       
  1822 	const TInt KOptMaxRecvUnitValueLen = 2; // correct value
       
  1823 	const TInt KOptMagicNumberValueLen = 4;
       
  1824 	const TInt KOptMruMinSize = 4;
       
  1825 
       
  1826 	RPppOption opt;
       
  1827 	TBool forceNak(EFalse);
       
  1828 	while (aRequestList.Remove(opt))
       
  1829 		{
       
  1830 		forceNak = EFalse; // Should the option be NAKed due to corruption?
       
  1831 
       
  1832 		switch (opt.OptType())
       
  1833 			{
       
  1834 		case KPppLcpOptMaxRecvUnit:
       
  1835 			// Check for correct MRU option length and MRU value >= 4
       
  1836 			if(KOptMaxRecvUnitValueLen == opt.ValueLength() && BigEndian::Get16(opt.ValuePtr()) >= KOptMruMinSize ) // valid option: Ack
       
  1837 				{
       
  1838 				aAckList.Append(opt);
       
  1839 				}
       
  1840 			else // invalid: NAK: put desired option, correct length
       
  1841 				{
       
  1842 				opt.SetValueLength(KOptMaxRecvUnitValueLen);
       
  1843 				//N.B. We NAK with our MRU, read from the .ini file.
       
  1844 				BigEndian::Put16(opt.ValuePtr(), static_cast<TUint16>(iMaxRecvSize));
       
  1845 				aNakList.Append(opt);
       
  1846 				}
       
  1847 			break;
       
  1848 
       
  1849 		case KPppLcpOptMagicNumber:
       
  1850 			if(KOptMagicNumberValueLen == opt.ValueLength()) // Correct length
       
  1851 				{
       
  1852 				iRemMagicNumber = BigEndian::Get32(opt.ValuePtr());
       
  1853 				// Magic number of zero is not allowed and results in a Nak.
       
  1854 				if (iRemMagicNumber == 0)
       
  1855 					{
       
  1856 					forceNak = ETrue;
       
  1857 					}
       
  1858 				}
       
  1859 			else // Invalid length: correct it and NAK.
       
  1860 				{
       
  1861 				opt.SetValueLength(KOptMagicNumberValueLen);
       
  1862 				forceNak = ETrue;
       
  1863 				}
       
  1864 
       
  1865 			// NAK if local and remote magic numbers are equal, or if
       
  1866 			// the option is corrupt.
       
  1867 			if((iRemMagicNumber == iLocMagicNumber) || forceNak)
       
  1868 			  	{
       
  1869 				TRAPD(result, NewMagicNumberL(iRemMagicNumber));
       
  1870 
       
  1871 				if(result == KErrNone)
       
  1872 					{
       
  1873 					BigEndian::Put32(opt.ValuePtr(), iRemMagicNumber);
       
  1874 					}
       
  1875 				else
       
  1876 					{
       
  1877 					LOG( iLogger->Printf(_L("CPppLcp::FsmCheckConfigRequest Error when using NewMagicNumberL iError[%d]"), result); )
       
  1878 					}
       
  1879 				aNakList.Append(opt);
       
  1880 				}
       
  1881 			else // Remote magic number option is OK and remote number != local number
       
  1882 				{
       
  1883 				aAckList.Append(opt);
       
  1884 				}
       
  1885 			break;
       
  1886 		case KPppLcpOptMultiLinkEndPointDescriminator:
       
  1887 	        aAckList.Append(opt);
       
  1888 			break;
       
  1889 
       
  1890 		default:
       
  1891     		ExtOptCheckConfigRequest(opt, aAckList, aNakList, aRejList);
       
  1892 			}
       
  1893 		}
       
  1894 	}
       
  1895 
       
  1896 EXPORT_C void CPppLcp::FsmApplyConfigRequest(RPppOptionList& aRequestList)
       
  1897 /**
       
  1898 Apply options in a received config request (that was ACK'd).
       
  1899 Upcall from the FSM.
       
  1900 
       
  1901 @param aRequestList LCP options to use
       
  1902 */
       
  1903 	{
       
  1904 	TMBufPktQIter iter(aRequestList);
       
  1905 	RPppOption opt;
       
  1906 
       
  1907 	while (opt = iter++, !opt.IsEmpty())
       
  1908 		{
       
  1909 		switch (opt.OptType())
       
  1910 			{
       
  1911 		case KPppLcpOptMaxRecvUnit:
       
  1912 			iMaxSendSize = BigEndian::Get16(opt.ValuePtr());
       
  1913 			break;
       
  1914 		case KPppLcpOptMagicNumber:
       
  1915 			iRemMagicNumber = BigEndian::Get32(opt.ValuePtr());
       
  1916 			break;
       
  1917 		default:
       
  1918 			ExtOptApplyConfigRequest(opt);
       
  1919 			break;
       
  1920 			}
       
  1921 		}
       
  1922 	}
       
  1923 
       
  1924 EXPORT_C void CPppLcp::FsmRecvConfigAck(RPppOptionList& aReplyList)
       
  1925 /**
       
  1926 Received a Config Ack - apply the options
       
  1927 Upcall from the FSM.
       
  1928 
       
  1929 @param aReplyList LCP options to use
       
  1930 */
       
  1931 	{
       
  1932 	TMBufPktQIter iter(aReplyList);
       
  1933 	RPppOption opt;
       
  1934 
       
  1935 	while (opt = iter++, !opt.IsEmpty())
       
  1936 		{
       
  1937 		switch (opt.OptType())
       
  1938 			{
       
  1939 		case KPppLcpOptMaxRecvUnit:
       
  1940 			iMaxRecvSize = BigEndian::Get16(opt.ValuePtr());
       
  1941 			break;
       
  1942 		case KPppLcpOptMagicNumber:
       
  1943 			// Magic number is OK
       
  1944 			SendIdentification();
       
  1945 			break;
       
  1946 		case KPppLcpOptCallback:
       
  1947 			CallbackRequestGranted();
       
  1948 			break;
       
  1949 		default:
       
  1950 			ExtOptRecvConfigAck(opt);
       
  1951 			break;
       
  1952 			}
       
  1953 		}
       
  1954 	}
       
  1955 
       
  1956 EXPORT_C void CPppLcp::FsmRecvConfigNak(RPppOptionList& aReplyList, RPppOptionList& aReqList)
       
  1957 /**
       
  1958 Modify request after receiving a Config Nak
       
  1959 Upcall from the FSM.
       
  1960 
       
  1961 @param aReplyList NAK'd LCP options
       
  1962 @param aReqList The associated original request to be modified
       
  1963 */
       
  1964 	{
       
  1965 	TMBufPktQIter iter(aReplyList);
       
  1966 	RPppOption opt;
       
  1967 
       
  1968 	while (opt = iter++, !opt.IsEmpty())
       
  1969 		{
       
  1970 		switch (opt.OptType())
       
  1971 			{
       
  1972 		case KPppLcpOptMaxRecvUnit:
       
  1973 			aReqList.ReplaceOption(opt);
       
  1974 			break;
       
  1975 		case KPppLcpOptMagicNumber:
       
  1976 			{
       
  1977 			iLocMagicNumber = BigEndian::Get32(opt.ValuePtr());
       
  1978 			if (iLocMagicNumber==iRemMagicNumber)
       
  1979 				{
       
  1980 				if (++iConsecMagic>KPppFsmNonConvergeLimit)
       
  1981 					{
       
  1982 					FsmAbort(KErrTimedOut);
       
  1983 					return;
       
  1984 					}
       
  1985 				}
       
  1986 			else
       
  1987 				iConsecMagic = 0;
       
  1988 			aReqList.ReplaceOption(opt);
       
  1989 			}
       
  1990 			break;
       
  1991 		default:
       
  1992 			ExtOptRecvConfigNak(opt, aReqList);
       
  1993 			break;
       
  1994 			}
       
  1995 		}
       
  1996 	}
       
  1997 
       
  1998 EXPORT_C void CPppLcp::FsmRecvConfigReject(RPppOptionList& aReplyList, RPppOptionList& aReqList)
       
  1999 /**
       
  2000 Modify request after receiving a Config Reject
       
  2001 Upcall from the FSM.
       
  2002 
       
  2003 @param aReplyList NAK'd LCP options
       
  2004 @param aReqList The associated original request to be modified
       
  2005 */
       
  2006 	{
       
  2007 	TMBufPktQIter iter(aReplyList);
       
  2008 	RPppOption opt;
       
  2009 
       
  2010 	while (opt = iter++, !opt.IsEmpty())
       
  2011 		{
       
  2012 		switch (opt.OptType())
       
  2013 			{
       
  2014 		case KPppLcpOptMaxRecvUnit:
       
  2015 		case KPppLcpOptMagicNumber:
       
  2016 			aReqList.RemoveOption(opt);
       
  2017 			break;
       
  2018 		//PG if call back is rejected take the link down
       
  2019 		case KPppLcpOptCallback:
       
  2020 			PhaseAborted(KErrIfCallbackNotAcceptable);
       
  2021 			break;
       
  2022 		default:
       
  2023 			ExtOptRecvConfigReject(opt, aReqList);
       
  2024 			break;
       
  2025 			}
       
  2026 		}
       
  2027 	}
       
  2028 
       
  2029 EXPORT_C TBool CPppLcp::FsmRecvUnknownCode(TUint8 aCode, TUint8 aId, TInt aLength, RMBufChain& aPacket)
       
  2030 /**
       
  2031 Process a packet with an otherwise unrecognised LCP opcode.
       
  2032 If processing of extended codes is enabled or the code can otherwise be
       
  2033 handled here, process it.
       
  2034 Upcall from the FSM.
       
  2035 
       
  2036 @param aCode Unrecognised opcode
       
  2037 @param aId Packet identifier
       
  2038 @param aLength Length of packet
       
  2039 @param aPacket MBuf chain containing received packet
       
  2040 
       
  2041 @return ETrue if the packet was handled
       
  2042 */
       
  2043 	{
       
  2044 	switch (aCode)
       
  2045 		{
       
  2046 	case KPppLcpIdentification:
       
  2047 		if(DoLcpExts())
       
  2048 			{
       
  2049 			if(aLength<=4)
       
  2050 				return ETrue;
       
  2051 			aPacket.TrimStart(4);
       
  2052 			TUint num = BigEndian::Get32(aPacket.First()->Ptr());
       
  2053 			if (num==iRemMagicNumber)
       
  2054 				{
       
  2055 				delete iRecvIdentification;
       
  2056 				iRecvIdentification = NULL;
       
  2057 				iRecvIdentification = HBufC8::New(aLength-8);
       
  2058 				if(!iRecvIdentification)
       
  2059 					return ETrue;
       
  2060 				TPtr8 des = iRecvIdentification->Des();
       
  2061 				aPacket.CopyOut(des, 4);
       
  2062 				}
       
  2063 			return ETrue;
       
  2064 			}
       
  2065 		else
       
  2066 			return EFalse;
       
  2067 
       
  2068 	case KPppLcpTimeRemaining:
       
  2069 		if(DoLcpExts())
       
  2070 			{
       
  2071 			if(aLength<=4)
       
  2072 				return ETrue;
       
  2073 			aPacket.TrimStart(4);
       
  2074 			TUint num = BigEndian::Get32(aPacket.First()->Ptr());
       
  2075 			if (num==iRemMagicNumber)
       
  2076 				{
       
  2077 				aPacket.TrimStart(4);
       
  2078 				iRecvTimeNotification.UniversalTime();
       
  2079 				iRecvTimeRemaining = BigEndian::Get32(aPacket.First()->Ptr());
       
  2080 				delete iRecvTimeRemMessage;
       
  2081 				iRecvTimeRemMessage=NULL;
       
  2082 				if (aLength>12)
       
  2083 					{
       
  2084 					iRecvTimeRemMessage = HBufC8::New(aLength-12);
       
  2085 					if(!iRecvTimeRemMessage)
       
  2086 						return ETrue;
       
  2087 					TPtr8 des = iRecvTimeRemMessage->Des();
       
  2088 					aPacket.CopyOut(des, 4);
       
  2089 					}
       
  2090 				}
       
  2091 			return ETrue;
       
  2092 			}
       
  2093 		else
       
  2094 			return EFalse;
       
  2095 
       
  2096 	case KPppLcpEchoRequest:
       
  2097 		{
       
  2098 		if(aLength < 8)  //Packet's length is less than the Min 8 bytes for a echo request.
       
  2099 			return ETrue;
       
  2100 		RMBufPacket pkt;
       
  2101 		RMBufPktInfo* info=NULL;
       
  2102 		TRAPD(ret, info = pkt.NewInfoL());
       
  2103 		if (ret!=KErrNone)
       
  2104 			return ETrue;
       
  2105 		// Reuse the existing packet buffer for our reply
       
  2106 		pkt.Assign(aPacket);
       
  2107 		TUint8* ptr = pkt.First()->Ptr();
       
  2108 		//check if the magic number matches the negotiated value.
       
  2109 		TUint magicNumber= BigEndian::Get32(ptr+4);
       
  2110 		if(magicNumber != iRemMagicNumber)
       
  2111 			{
       
  2112 			LOG( iPppLcp->iLogger->Printf(_L("PPP detected a wrong magic number in echo request.")); )
       
  2113 			return ETrue; //Just discard this echo request.
       
  2114 			}
       
  2115 		info->iLength = BigEndian::Get16(ptr+2);
       
  2116 		TPppAddr::Cast(info->iDstAddr).SetProtocol(iPppId);
       
  2117 		BigEndian::Put32(ptr+4, iLocMagicNumber);
       
  2118 		*ptr = KPppLcpEchoReply;
       
  2119 		// If the frame to be sent is too large, lop off the end to make it fit.
       
  2120  		__ASSERT_DEBUG(iPppLcp->MaxTransferSize() > 0, PppPanic(EPppPanic_InvalidData));
       
  2121  		if (info->iLength > iPppLcp->MaxTransferSize())
       
  2122  			{
       
  2123  			pkt.TrimEnd(iPppLcp->MaxTransferSize());
       
  2124  			info->iLength = iPppLcp->MaxTransferSize();
       
  2125   			}
       
  2126 		pkt.Pack();
       
  2127 		SendFrame(pkt);
       
  2128 		}
       
  2129 		return ETrue;
       
  2130 	case KPppLcpEchoReply:
       
  2131 		{
       
  2132 		// Call CPppLrd::RecvEchoReply
       
  2133 		iPppLrd->RecvEchoReply(aId);
       
  2134 		return ETrue;
       
  2135 		}
       
  2136 	case KPppLcpDiscardRequest:
       
  2137 		return ETrue;
       
  2138 	default:
       
  2139 		break;
       
  2140 		}
       
  2141 	return EFalse;
       
  2142 	}
       
  2143 
       
  2144 //
       
  2145 // Other methods
       
  2146 //
       
  2147 
       
  2148 void CPppLcp::NewMagicNumberL(TUint& aMagicNumber)
       
  2149 /**
       
  2150 Generate a new magic number, based upon existing number,
       
  2151 machine unique ID and tick count.
       
  2152 
       
  2153 @param aMagicNumber Magic number to update
       
  2154 */
       
  2155 	{
       
  2156 
       
  2157 	TPckg<TUint> randDes(aMagicNumber);
       
  2158 	do
       
  2159 		{
       
  2160 		TRandom::RandomL(randDes);
       
  2161 		}
       
  2162 		while (aMagicNumber==0);
       
  2163 	}
       
  2164 
       
  2165 void CPppLcp::CancelRead()
       
  2166 /**
       
  2167 Unused
       
  2168 */
       
  2169 	{
       
  2170 	}
       
  2171 
       
  2172 TUint8 CPppLcp::SendEchoRequest()
       
  2173 /**
       
  2174 Send an LCP Echo Request frame.
       
  2175 Called by CPppLrd::TimerComplete periodically
       
  2176 
       
  2177 @return On success, the Identifier that was selected
       
  2178 so CPppLrd can match the answer to the request.
       
  2179 On failure, 0 (safe because the identifier can't be 0)
       
  2180 */
       
  2181 	{
       
  2182 	TUint8	returnValue = 0;
       
  2183 	RMBufPacket pkt;
       
  2184 	const TUint pktLen = 4+4;
       
  2185 	TUint8* ptr = NewPacket(pkt, pktLen);
       
  2186 	if (ptr == NULL)
       
  2187 		{
       
  2188 		return returnValue;
       
  2189 		}
       
  2190 	*ptr++ = (TUint8)KPppLcpEchoRequest;
       
  2191 	*ptr++ = (returnValue = FsmNewId());
       
  2192 	BigEndian::Put16(ptr, (TUint16)pktLen);
       
  2193 	BigEndian::Put32(ptr+2, (TUint32)iLocMagicNumber);
       
  2194 	pkt.Pack();
       
  2195 	SendFrame(pkt);
       
  2196 	return returnValue;
       
  2197 	}
       
  2198 
       
  2199 void CPppLcp::SendIdentification()
       
  2200 /**
       
  2201 Send an LCP Identification frame (RFC 1570).
       
  2202 */
       
  2203 	{
       
  2204 	if(!DoLcpExts())
       
  2205 		return;
       
  2206 	TPtrC8 id = _L8("Symbian Epoc");
       
  2207 	RMBufPacket pkt;
       
  2208 	const TUint pktLen = 4+4+id.Length();
       
  2209 	TUint8* ptr = NewPacket(pkt, pktLen);
       
  2210 	if (ptr == NULL)
       
  2211 		{
       
  2212 		return;
       
  2213 		}
       
  2214 	*ptr++ = (TUint8)KPppLcpIdentification;
       
  2215 	*ptr++ = FsmNewId();
       
  2216 	BigEndian::Put16(ptr, (TUint16)pktLen);
       
  2217 	BigEndian::Put32(ptr+2, (TUint32)iLocMagicNumber);
       
  2218 
       
  2219 	pkt.CopyIn(id, 4+4);
       
  2220 	pkt.Pack();
       
  2221 	SendFrame(pkt);
       
  2222 	}
       
  2223 
       
  2224 void CPppLcp::StopProtocol(TUint aProtocol)
       
  2225 /**
       
  2226 One of the NCP protocols has been shut down, so kill it.
       
  2227 Searches for the registered protocol handler based on the protocol ID.
       
  2228 
       
  2229 @param aProtocol PPP protocol number
       
  2230 */
       
  2231 	{
       
  2232 	MPppRecvr* rcvr;
       
  2233 
       
  2234 
       
  2235 	TDblQueIter<MPppRecvr> iter(iRecvrList);
       
  2236 	while (rcvr = iter++, rcvr!=NULL)
       
  2237 		{
       
  2238 		if (aProtocol == rcvr->iPppId)
       
  2239 			{
       
  2240 			/*
       
  2241 			*	Kill Me
       
  2242 			*/
       
  2243 			rcvr->KillProtocol();
       
  2244 
       
  2245 			}
       
  2246 		}
       
  2247 	}
       
  2248 
       
  2249 void CPppLcp::PppNewCompressor(const CPppCompressor* aCompressor)
       
  2250 /**
       
  2251 Indicate that the compression protocol handler is ready.
       
  2252 Called from CPppCcp.
       
  2253 
       
  2254 @param aCompressor Compressor object, or NULL to indicate object is
       
  2255 no longer available
       
  2256 */
       
  2257 	{
       
  2258 	if (iPppLink != NULL)
       
  2259 		{
       
  2260 		iPppLink->NewCompressor(aCompressor);
       
  2261 		}
       
  2262 	}
       
  2263 
       
  2264 void CPppLcp::PppUnloadCompressor()
       
  2265 /**
       
  2266 Unload the compression module after a compressed packet is rejected.
       
  2267 Upcall from the FSM.
       
  2268 */
       
  2269 	{
       
  2270 	if (iPppCcp != NULL)
       
  2271 		{
       
  2272 		iPppCcp->UnloadCompressor();
       
  2273 		}
       
  2274 	}
       
  2275 
       
  2276 void CPppLcp::PppNewDeCompressor(const CPppDeCompressor* aDeCompressor)
       
  2277 /**
       
  2278 Indicate that the decompression protocol handler is ready.
       
  2279 Called from CPppCcp.
       
  2280 
       
  2281 @param aDeCompressor Decompressor object, or NULL to indicate object is no longer available
       
  2282 */
       
  2283 	{
       
  2284 	if (iPppLink != NULL)
       
  2285 		{
       
  2286 		iPppLink->NewDeCompressor(aDeCompressor);
       
  2287 		}
       
  2288 	}
       
  2289 
       
  2290 TInt CPppLcp::Notification(TAgentToNifEventType aEvent, void * aInfo)
       
  2291 /**
       
  2292 Notification from Agent
       
  2293 
       
  2294 @param aEvent Event type
       
  2295 @param aInfo Data relating to event
       
  2296 
       
  2297 @return Error code
       
  2298 */
       
  2299 	{
       
  2300 	switch (aEvent)
       
  2301 		{
       
  2302 	case EAgentToNifEventTypeModifyInitialTimer:
       
  2303 
       
  2304 		return KErrNone;
       
  2305 	case EAgentToNifEventTypeDisableTimers:
       
  2306 		iPppLrd->EnableOrDisableTimer(EFalse);
       
  2307 		return KErrNone;
       
  2308 	case EAgentToNifEventTypeEnableTimers:
       
  2309 		iPppLrd->EnableOrDisableTimer(ETrue);
       
  2310 		return KErrNone;
       
  2311 	case EAgentToNifEventTypeGetDataTransfer:
       
  2312 		{
       
  2313 		//===========================================
       
  2314 		// JGG PPP CHANGE
       
  2315 		TPckg<RPacketContext::TDataVolume>* dataPackage = (TPckg<RPacketContext::TDataVolume>*) aInfo;
       
  2316 		RPacketContext::TDataVolume& data = (*dataPackage)();
       
  2317 		//TPckg<RGprsContext::TDataVolume>* dataPackage = (TPckg<RGprsContext::TDataVolume>*) aInfo;
       
  2318 		//RGprsContext::TDataVolume& data = (*dataPackage)();
       
  2319 		//===========================================
       
  2320 		iPppLink->GetDataTransfer(data);
       
  2321 		return KErrNone;
       
  2322 		}
       
  2323 	default:
       
  2324 		break;
       
  2325 		}
       
  2326 		return KErrNotSupported;
       
  2327 	}
       
  2328 
       
  2329 EXPORT_C TBool CPppLcp::FsmAckOptionsValid(RPppOptionList& aList, RPppOptionList& aRequestList)
       
  2330 /**
       
  2331 Check if the option list specified matches the original Config-Request option list.
       
  2332 
       
  2333 Used for conformance to RFC1661 sections 5.2 and 5.4 (the option list in a Config-Ack or
       
  2334 Config-Reject must exactly match the option list in the original Config-Request - same
       
  2335 option values in the same order with no new options appended).
       
  2336 
       
  2337 @param aList option list to check against (e.g. from a Config-Ack or Config-Reject etc).
       
  2338 */
       
  2339 	{
       
  2340 	return aList.EqualTo(aRequestList);
       
  2341 	}
       
  2342 
       
  2343 EXPORT_C TBool CPppLcp::FsmRejectOptionsValid(RPppOptionList& aList, RPppOptionList& aRequestList)
       
  2344 /**
       
  2345 Check if the option list specified matches the original Config-Request option list.
       
  2346 
       
  2347 Used for conformance to RFC1661 sections 5.2 and 5.4 (the option list in a Config-Ack or
       
  2348 Config-Reject must exactly match the option list in the original Config-Request - same
       
  2349 option values in the same order with no new options appended).
       
  2350 
       
  2351 @param aList option list to check against (e.g. from a Config-Ack or Config-Reject etc).
       
  2352 */
       
  2353 	{
       
  2354 	return aList.IsSubsetOf(aRequestList);
       
  2355 	}
       
  2356 
       
  2357 EXPORT_C TBool CPppLcp::FsmConfigRequestOptionsValid(RPppOptionList& aList)
       
  2358 /**
       
  2359 Check if any RFC1661 options are duplicated in the specified option list.
       
  2360 
       
  2361 Used for conformance to RFC1661 section 6:
       
  2362 
       
  2363 	"... (None of the Configuration Options in this specification can be listed more than once.)..."
       
  2364 
       
  2365 Note that this only checks for options in RFC1661 specification and not *all* PPP options
       
  2366 (hence the "RFC1661" prefix to the method name).
       
  2367 
       
  2368 @param aList option list to check .
       
  2369 */
       
  2370 	{
       
  2371 	const TInt KMinOption = KPppLcpOptMaxRecvUnit;
       
  2372 	const TInt KMaxOption = KPppLcpOptAddrCtrlCompress;
       
  2373 
       
  2374 	ASSERT(KMinOption >= 0 && KMaxOption >= 0 && KMinOption <= KMaxOption);	// sanity
       
  2375 
       
  2376 	TUint8 optionCount[KMaxOption + 1] = { 0 };
       
  2377 
       
  2378 	TMBufPktQIter iter(aList);
       
  2379 	RPppOption opt;
       
  2380 
       
  2381 	opt = iter++;
       
  2382 	while (!opt.IsEmpty())
       
  2383 		{
       
  2384 		TUint8 optType = opt.OptType();
       
  2385 		if (optType >= KMinOption && optType <= KMaxOption)
       
  2386 			{
       
  2387 			if (++optionCount[optType] == 2)		// duplicated option...
       
  2388 				{
       
  2389 				switch (optType)					// ...is it one of the RFC1661 options ?
       
  2390 					{
       
  2391 				case KPppLcpOptMaxRecvUnit:
       
  2392 				case KPppLcpOptAuthenticationProtocol:
       
  2393 				case KPppLcpOptQualityProtocol:
       
  2394 				case KPppLcpOptMagicNumber:
       
  2395 				case KPppLcpOptProtocolCompress:
       
  2396 				case KPppLcpOptAddrCtrlCompress:
       
  2397 					return EFalse;
       
  2398 				default:
       
  2399 					break;
       
  2400 					}
       
  2401 				}
       
  2402 			}
       
  2403 		opt = iter++;
       
  2404 		}
       
  2405 	return ETrue;
       
  2406 	}
       
  2407 
       
  2408 void CPppLcp::NcpUp()
       
  2409 	{
       
  2410 	++iNcpUpCount;
       
  2411 	if (AllNcpsUp())
       
  2412 		{
       
  2413 		FlowUp();
       
  2414 		}
       
  2415 	}
       
  2416 
       
  2417 TBool CPppLcp::AllNcpsUp()
       
  2418 	{
       
  2419 	return (iNcpUpCount == iOpenCount);
       
  2420 	}
       
  2421 
       
  2422 #ifdef __FLOG_ACTIVE
       
  2423 const TText8* CPppLcp::GetMMStateName() const
       
  2424 	{
       
  2425 		switch(iMMState)
       
  2426 			{
       
  2427 			case EStopped:
       
  2428 				return _S8("Stopped");
       
  2429 	      	case EStarting:
       
  2430 				return _S8("Starting");
       
  2431 	      	case EStarted:
       
  2432 				return _S8("Started");
       
  2433 	      	case EStopping:
       
  2434 				return _S8("Stopping");
       
  2435 	      	default:
       
  2436 				return _S8("<Unknown State>");
       
  2437 			}
       
  2438 	}
       
  2439 #endif