linklayerprotocols/pppnif/te_ppp/dummyppp/src/dummypppnif.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 16 Apr 2010 16:36:59 +0300
changeset 14 b33c3d136b7e
parent 0 af10295192d8
permissions -rw-r--r--
Revision: 201015 Kit: 201015

// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// This module contains the code for the dummy PPP Nif class which communicates with the upper PPP Nif
// via PPP "proxy"
// 
//

#include <comms-infras/nifif.h>
#include <nifvar.h>
#include <nifutl.h>
#include <es_mbuf.h>
#include <comms-infras/commsdebugutility.h>
#include <connectprog.h>
#include <in_chk.h>
#include <metadatabase.h>
#include <commsdattypeinfov1_1.h>

//New ppp progress states file
#include "PppProg.h"

#include "dummypppnif.h"
#include "DummyPPPNifVar.h"


const TInt KLoWatMark = 2;
const TInt KHiWatMark = 6;


// Internal flag bits used  
const TUint KDummyPPPSendBusy = 0x00001000;
const TUint KDummyPPPApplyPending = 0x00010000;

//only for generating the logs
_LIT(KCodeTextString,"	%s [0x%02x]");
_LIT(KCodeTextWithoutSpacesString,"	%s [0x%02x]");
_LIT(KIdentifierLengthString,"	Id = 0x%02x, Len = %d");
_LIT(KLengthString,"	Length = %d");
_LIT(KLengthString2,"	    Length = 0x%02x");
_LIT(KTCPLengthString,"	    Length = %d, Hdr len = %d");
_LIT(KUDPLengthPortString,"	    Length = %d, Src port = %d, Dst port = %d");
_LIT(KBytesRemainingString,"        %d byte%s remaining");
_LIT(KLcpCodeString,"	Code = %s [0x%02x]");
_LIT(KCodeString,"	Code = 0x%02x");
_LIT(KCodeString2,"	Code = 0x%04x");
_LIT(KProtocolString,"	Protocol = 0x%04x");
_LIT(KNumberString,"	Number = 0x%08x");
_LIT(KSecondsString,"	Seconds = %d");
_LIT(KSizeString,"	    Size = %d");
_LIT(KMapString,"	    Map = 0x%08x");
_LIT(KProtocolTextString,"	    Protocol = %s [0x%04x]");
_LIT(KLcpOptFcsTypeString,"	    Types =%s%s%s");
_LIT(KMaximumBytesString,"	    Maximum bytes = %d");
_LIT(KUserNameString,"	Username = \"%S\"");
_LIT(KPasswordString,"	Password = \"%S\"");
_LIT(KMessageString,"	Message = \"%S\"");
_LIT(KDelayString,"	    Delay=%d\n");
_LIT(KNameString,"	Name = \"%S\"");
_LIT(KChangeMaskString,"	Change Mask = 0x%x: ");
_LIT(KChecksumString,"	Checksum = 0x%x");
_LIT(KChecksumString3,"	    Chksum = 0x%04x (0x%04x) !!!");
_LIT(KConnectionString,"	    Connection = 0x%x");
_LIT(KHdrLengthString,"	Length = %d, Hdr len = %d");
_LIT(KIDFragmentString,"	Id = 0x%04x, Fragment = %d %s%s%s");
_LIT(KSrcDstAddrString,"	Src = %d.%d.%d.%d, Dst = %d.%d.%d.%d");
_LIT(KIpv6SrcAddress,"    Src = %x:%x:%x:%x:%x:%x:%x:%x");
_LIT(KIpv6DstAddress,"    Dst = %x:%x:%x:%x:%x:%x:%x:%x");
_LIT(KIpv6Class,"    Class = %d");
_LIT(KIpv6FlowLabel,"    FlowLabel = %d");
_LIT(KIpv6PayloadLen,"    Payload = %d words");
_LIT(KIpv6NextHeadType,"    Next Header type is [%d]");
_LIT(KIpv6HopLimit,"    Hop Limit is %d");
_LIT(KIpv6UnknownHeadType,"    Unknown next header: [%d]");
_LIT(KConnectionNoString,"	Connection number [0x%02x]");
_LIT(KRemoteAddrString,"	    Remote Address = %d.%d.%d.%d");
_LIT(KOurAddrString,"	    Our Address = %d.%d.%d.%d");
_LIT(KMaxSlotString,"	      Max Slot Id = %d");
_LIT(KCompSlotString,"	      Comp Slot Id = %d");
_LIT(KAddrString,"	    Address = %d.%d.%d.%d");
_LIT(KPortString,"	    Src port = %d, Dst port = %d");
_LIT(KWindowUrgentString,"	    Window = %d, Urgent = %d");
_LIT(KSeqAckString,"	    Seq = 0x%08x, Ack = 0x%08x");
_LIT(KFlagsString,"	    Flags = %s%s%s%s%s%s");

#define EIGHT_SPACE_MARGIN			_S("        ")
#define FOURTEEN_SPACE_MARGIN		_S("              ")

/*
 * This sections defines a whole load of constants etc... not very exciting
 */
#ifdef __FLOG_ACTIVE
_LIT8(KDummyPppLogFolder	,"dummypppnif");
_LIT8(KDummyPppLogFile, "dummypppnif.txt");
#endif // #ifdef __FLOG_ACTIVE

_LIT(KEndOfLine, "\n");

/*
 * The Link class
 */

CDummyPPPLink::CDummyPPPLink(CNifIfFactory& aFactory)
	: CNifIfLink(aFactory)
	{
	CDummyNifLog::Printf(_L("Dummy PPP Link Created\r\n"));
	}

CDummyPPPLink::~CDummyPPPLink()
	{
	CDummyNifLog::Printf(_L("Dummy PPP Link Destroyed\r\n"));
	TimerDelete();
	iNifIf->End();
	iNifIf->CloseLog();
	}
 
void CDummyPPPLink::OpenL()
//
// Start connect establishment
//
	{
	switch (iState)
		{
	case EDummyPPPLinkConnecting:
	case EDummyPPPLinkOpen:
		return;
	case EDummyPPPLinkClosed:
		iState = EDummyPPPLinkConnecting;
		break;
	default:
		return;
		}
	CDummyNifLog::Printf(_L("Dummy PPP LinkOpen\r\n"));
	}

void CDummyPPPLink::LinkDown(TInt /*aStatus*/)
//
// Link down - drop out of packet mode
// and notify reason
//
	{
	CDummyNifLog::Printf(_L("Dummy PPP LinkDown\r\n"));
	iState = EDummyPPPLinkClosed;
	}
 
TInt CDummyPPPLink::Send(RMBufChain& aPdu, TAny* aSource)
	{
	CDummyNifLog::Printf(_L("Dummy PPP LinkSend\r\n"));

	return iNifIf->Send(aPdu, aSource);
	}
TInt CDummyPPPIf::Send(RMBufChain& aPacket, TAny* )
{
	
	//To send over serial port to NTRAS
	//return Send(aPacket, iDummyPPPId);

	CDummyNifLog::Write(_L("DummyPPP::RecvdfromPPP\n"));
	CDummyNifLog::Printf(_L("Dummy PPP Send\r\n"));
	logUser->Dump(aPacket, KDummyPPPRecvChannel);

	//Added to send to PPP interface directly
	if(!ProcessPPPPacket(aPacket))
	{
		if(SwitchIPHeaders(*ptrTransPktPPP))
		{
			SendtoPPP(*ptrTransPktPPP);
		}

	}
	return iSendFlowOn;
}

TInt CDummyPPPIf::SwitchIPHeaders(RMBufChain& aPacket)
{
	CDummyNifLog::Printf(_L("DummyPPP::SwitchIPHeaders\r\n"));
	TInt iResult = 0;
	// this received data has already been looped back...
	// get the ip header from the RMBufChain
	TInet6HeaderIP4* ip4 = (TInet6HeaderIP4*) aPacket.First()->Next()->Ptr();
	// get the udp header as well - assume only udp traffic here
	TInet6HeaderUDP* udp = (TInet6HeaderUDP*) ip4->EndPtr();

	TUint dstPort = udp->DstPort();
	if(KDummyPppNifCmdPort == dstPort)
	{	
		// let's use the first payload byte as the command byte
		if(*(udp->EndPtr())== KForceDisconnect)
		{
			CDummyNifLog::Printf(_L("DummyPPP::Sending LinkLayerDown signal\r\n"));
			// do some action
			iNotify->IfProgress(KLinkLayerClosed, KErrCommsLineFail);
			iNotify->LinkLayerDown(KErrCommsLineFail, MNifIfNotify::EDisconnect);
		}
	}
	else
	{

		// update the headers (addresses, checksums etc) to UpdateHeaders(ip4, udp);
		// swap over the destination and source addresses
		TUint32 tempSrc,tempDest;
		tempSrc = ip4->SrcAddr();
		tempDest = ip4->DstAddr();
    
		ip4->SetSrcAddr(tempDest);
		ip4->SetDstAddr(tempSrc);

		TUint tempChksum;
		tempChksum = ip4->Checksum();
		// we've changed the ip hdr so need to recalculate the ip hdr checksum
		ip4->SetChecksum(0); 
		tempChksum = TChecksum::Calculate((TUint16*)ip4, ip4->HeaderLength());
		tempChksum = TChecksum::ComplementedFold(tempChksum);
		ip4->SetChecksum(tempChksum);
		//ip4->SetChecksum(TChecksum::ComplementedFold(TChecksum::Calculate((TUint16*)ip4, ip4->HeaderLength())));

		// also want to set the udp checksum to zero cos it will be wrong now that we have 
		// changed the ip hdr - just set to zero and it is ignored
		udp->SetChecksum(0);
		iResult = 1;
	}
	return iResult;
}
void CDummyPPPIf::SendtoPPP(RMBufChain& aPacket)
{
	CDummyNifLog::Printf(_L("Dummy PPP SendtoPPP\r\n"));
	iSendNumBufs += aPacket.NumBufs();
	iLink->iSendQ.Append(aPacket);

	switch (iLink->iState)
		{
	case EDummyPPPLinkConnecting:
		aPacket.Free();
		break;
	case EDummyPPPLinkOpen:
		if (iSendFlowOn && iSendNumBufs>=iSendHiWat)
			{
			iSendFlowOn = EFalse;
			CDummyNifLog::Printf(_L("DummyPPP::SendtoPPP() Flow off, iSendNumBufs %d"), iSendNumBufs);
			}
		else if (!(iFlags & KDummyPPPSendBusy))
			DoSendtoPPP();
		break;
	case EDummyPPPLinkClosed:
		{
		TRAPD(err, iLink->OpenL());
		aPacket.Free();
		}
		break;
	default:
		aPacket.Free();
		break;
		}
	
	iSendCallBack->CallBack();
}

TInt CDummyPPPIf::SendCallBack(TAny* aCProtocol)
	{
	((CDummyPPPIf*)aCProtocol)->DoSendtoPPP();
	return 0;
	}
void CDummyPPPIf::DoSendtoPPP()
{
	if (iFlags & KDummyPPPSendBusy)
		return;
	
    if (ipktRecvPPP.IsEmpty())
	{
   		RMBufPacket pkt;
		if (!iLink->iSendQ.Remove(pkt))
		{
			iSendNumBufs=0; // Must be so
			return;
		}
	
		CDummyNifLog::Write(_L("DummyPPP::DoSendtoPPP()\n"));
		logUser->Dump(pkt, KDummyPPPSendChannel);

		// Get next packet from send queue
		do
			{
			iFlags |= KDummyPPPSendBusy;
			iSendNumBufs -= pkt.NumBufs();
			iProtocol->Process(pkt, (CProtocolBase*)this);

			// the following Free() may not actually do anything if the packet has already been freed.
			pkt.Free();

			if (!iSendFlowOn && iSendNumBufs<iSendLoWat)
				{
				CDummyNifLog::Printf(_L("DummyPPP::DoSendtoPPP(): Flow on, iSendNumBufs %d"), iSendNumBufs);
				iSendFlowOn = ETrue;
				//for CppLcp's LinkFlowOn()
				iProtocol->StartSending(iProtocol);
				}
			} while (iLink->iSendQ.Remove(pkt));
		iFlags &= ~KDummyPPPSendBusy;
	}
}

TInt CDummyPPPIf::ProcessPPPPacket(RMBufChain& aPacket)
/**
 * Processes all packets received from PPP
 *
 * @param RMBufChain& aPacket
 * @returns nonzero if completed task
 * @returns 0 if need to send it to PPP
 */
{
	// Check if Handle ConfigRequest, ConfigAck, ConfigNak 
	//not responding to ConfigReject
	CDummyNifLog::Printf(_L("Dummy PPP ProcessPPPPacket\r\n"));
    TUint result = 0;

	result = DecodePacket(aPacket);
	if(result == 1) 
	{	if(iCodeRec == KPppLcpConfigReject)
		{
			//Panic as DpppLink does not respond to protocol reject
		}
		else
		{
			if(((iCodeRec == KPppLcpConfigAck)
				||(iCodeRec == KPppLcpConfigNak)
				||(iCodeRec == KPppLcpConfigRequest))
				&&(iDummyPPPState<EDummyPPPFsmOpened))
			{
				ProcessConfig();
			}
			else
			{
				ProcessPAPandIPCP();
			}
		}
		ipktRecvPPP.Free();
	}
    if(result == 0)
	{
		//Added to initialize the SendPPP index	
		ipktRecvPPP.Pack();
		ptrTransPktPPP = &ipktRecvPPP;
		SetupSendPPP();
	}
	return result;
}

TInt CDummyPPPIf::DecodePacket(RMBufChain& aPacket)
/**
 * Decodes RMBufChain received from PPP
 *
 * @param RMBufChain& aPacket
 * @returns 1 if need processing further
 * @returns 0 if need to send it to PPP
 * @returns 2 if packet is discarded
 */
{
	TInt result = 0;
	
	// N.B. ipktRecvPPP must be freed at the end of the previous receive / send sequence.
	// Freeing it here merely covers for a defect where it is not freed as expected.
	// Doubly freeing RMBufChain does not result in error. 
	ipktRecvPPP.Free();
	
	// If ipktRecvPPP not Freed, Assign Panics.
	ipktRecvPPP.Assign(aPacket);
	ipktRecvPPP.Unpack();
	RMBufPktInfo* info = ipktRecvPPP.Info();

	CDummyNifLog::Printf(_L("Dummy PPP DecodePacket\r\n"));
	// Extract and drop LCP header
	ipktRecvPPP.Align(4);
	TUint8* ptr = ipktRecvPPP.First()->Ptr();
	iCodeRec = *ptr++;
	iIdRec = *ptr++;
	iLenRec = BigEndian::Get16(ptr);
	
	// Check packet length is OK
	if (info->iLength<iLenRec || info->iLength<4 || info->iLength!=iLenRec)
	{
		// Too short!
		ipktRecvPPP.Free();
		return result;
	}
	else 
	{
		if (info->iLength>iLenRec)
			ipktRecvPPP.TrimEnd(iLenRec);
	}

	if(iCodeRec == KPppLcpConfigReject)
	{
		//not responding to protocol reject
		return result;
	}

	// If op is unknown
	switch (iCodeRec)
		{
	case KPppLcpConfigAck:
	case KPppLcpConfigNak:
		// Filter out bad acks
		if (iDummyPPPState>=EDummyPPPFsmReqSent && iIdRec!=iDummyPPPRequestId)
			break;
		else
			iDummyPPPRequestId |= KPppRequestIdAnswered;
		// fall through ...
	case KPppLcpConfigRequest:
		// Option negotiation ops
		// Split the MBuf chain in separate options

		//if(len<=4)
		if(iLenRec<4)
			break;
		
		//
		// Hmmm sometimes we receive a Config request of Length 4
		// i.e. no options Send a Config ACK
		// 
		if ( (iLenRec == 4) && (iCodeRec == KPppLcpConfigRequest))
			{
			result = 1;
			break;
			}
		if (iLenRec == 4)
			{
			break;
			}
		else
			{
			ipktRecvPPP.TrimStart(4);
			//ProcessConfig(op, id, len-4, pkt);
			result = 1;
			break;
			}
	case KPppLcpTerminateAck:
		//To be opened only in case if Dummy PPPNif sends Terminate Request so blocked

		// Filter out bad acks
		//if ((iDummyPPPState==EPppFsmClosing || iDummyPPPState==EPppFsmStopping) && id!=iTerminateId)
		//	break;
		//else
		//	iTerminateId |= KPppRequestIdAnswered;
		// fall through ...
	case KPppLcpTerminateRequest:
		if(iLenRec<4)
			break;

		ipktRecvPPP.TrimStart(4);
		ProcessTerminate();
		result = 2;
		break;
	
	default:
		break;
	}
	//pkt.Free();
	if(iDummyPPPState==EDummyPPPFsmIPOpen)
		result = 0;
	return result;

	}

void CDummyPPPIf::ProcessConfig()
	{	

	// Split the recvd packet into separate options
	// placing each option in a queue where it can be
	// easily parsed and manipulated in the upcall handlers.
	RPppOptionList rcvlist;	// Recvd list of options
 
	
	RPppOptionList acklist;	// List of Ack'd options - only valid of the following are empty
	RPppOptionList naklist;	// List of Nak'd options - only valid of the following is empty
	RPppOptionList rejlist;	// List of Rejected options

	CDummyNifLog::Printf(_L("Dummy PPP ProcessConfig\r\n"));

	enum TDummyPPPResult { ENop, EAck, ENak, ERej };

	TDummyPPPResult reply = ENop;

    TRAPD(err, rcvlist.SetL(ipktRecvPPP));
	if (err!=KErrNone)
		return;

	if (iCodeRec == KPppLcpConfigRequest)
		{
		// About to drop out of opened state to need to reset things
		// BEFORE the new request is processed.
		if (iDummyPPPState == EDummyPPPFsmOpened)
			{
			TRAPD(err, InitialiseConfigRequestL());
			if (err != KErrNone)
				{
				CDummyNifLog::Printf(_L("Dummy PPP InitialiseConfigRequestL failed\r\n"));
				return;
				}
			}
		
		// Check options, and split into list of OK, Bad and Unknown
		// Note - the naklist options will have been updated to
		// contain acceptable values.
		if (iCodeRec==KPppLcpConfigRequest)
			CheckRecvConfigRequest(rcvlist, acklist, naklist, rejlist);

		if (!rejlist.IsEmpty())
			{
			reply = ERej;
			naklist.Free();
			acklist.Free();
			}
		else if (!naklist.IsEmpty())
			{
			reply = ENak;
			acklist.Free();
			}
		else if (!acklist.IsEmpty())
			{
			reply = EAck;
			SetupConfigRequest(acklist);
			}
			
			//Added to initialize the SendPPP index
			ipktRecvPPP.Pack();
			ptrTransPktPPP = &ipktRecvPPP;
		}		

	// State processing

	switch (iDummyPPPState)
		{

	case EDummyPPPFsmInitial:
	case EDummyPPPFsmStarting:
		TRAPD(err, InitialiseConfigRequestL());
		if (err==KErrNone)
			SendConfigRequest();
		SetState(EDummyPPPFsmReqSent);
	case EDummyPPPFsmClosing:
	case EDummyPPPFsmStopping:
		break;
	case EDummyPPPFsmClosed:
		SetPppId(KPppIdLcp);
		SendTerminateAck();
		break;

	case EDummyPPPFsmStopped:
		switch (iCodeRec)
			{
		case KPppLcpConfigRequest:
			TRAPD(err, InitialiseConfigRequestL());
			if (err==KErrNone)
			{
				SendConfigRequest();
				SetPppId(KPppIdLcp);
			}
			switch (reply)
				{
			case EAck:
				SendConfigReply(acklist, KPppLcpConfigAck);
				SetState(EDummyPPPFsmAckSent);
				break;
			case ENak:
				SendConfigReply(naklist, KPppLcpConfigNak);
				SetState(EDummyPPPFsmReqSent);
				break;
			case ERej:
				SendConfigReply(rejlist, KPppLcpConfigReject);
				SetState(EDummyPPPFsmReqSent);
				break;
			default:
				break;
				}
			break;
		case KPppLcpConfigAck:
		case KPppLcpConfigNak:
		//Not responding to a reject
		//case KPppLcpConfigReject:
			SetPppId(KPppIdLcp);
			SendTerminateAck();
			break;
			}
		break;
	
	case EDummyPPPFsmReqSent:
		switch (iCodeRec)
			{
		case KPppLcpConfigRequest:
			switch (reply)
				{
			case EAck:
				SendConfigReply(acklist, KPppLcpConfigAck);
				SetState(EDummyPPPFsmAckSent);
				break;
			case ENak:
				// RFC 1661 4.6
				if(CheckMaxFailureExceeded() == TRUE)
					SendConfigReply(naklist, KPppLcpConfigReject);
				else
					{
					DecrementDummyPPPMaxFailureCount();
					SendConfigReply(naklist, KPppLcpConfigNak);
					}
				break;
			case ERej:
				SendConfigReply(rejlist, KPppLcpConfigReject);
				SetState(EDummyPPPFsmReqSent);
				break;
			default:
				break;
				}
			break;
		case KPppLcpConfigAck:
			InitRestartCountForConfig();
			CheckRecvConfigAck(rcvlist);
			SetState(EDummyPPPFsmAckRecvd);
			break;
		case KPppLcpConfigNak:
			InitRestartCountForConfig();
			CheckRecvConfigNak(rcvlist, iDummyPPPRequestList);
			//SendConfigRequestAfterNak(rcvlist);
			SetNewId();
			SendConfigRequest();
			break;
		case KPppLcpConfigReject:
			//Not responding to a reject
			//InitRestartCountForConfig();
			//CheckRecvConfigReject(rcvlist, iDummyPPPRequestList);
			//SendConfigRequestAfterReject(rcvlist);
			//SetNewId();
			//SendConfigRequest();
			break;
			}
		break;
	
	case EDummyPPPFsmAckRecvd:
		switch (iCodeRec)
			{
		case KPppLcpConfigRequest:
			switch (reply)
				{
			case EAck:
				SendConfigReply(acklist, KPppLcpConfigAck);
				SetState(EDummyPPPFsmOpened);
				//As external option negotiation complete
				iFlags |= KDummyPPPApplyPending; 
				break;
			case ENak:
				// RFC 1661 4.6
				if(CheckMaxFailureExceeded() == TRUE)
					SendConfigReply(naklist, KPppLcpConfigReject);
				else
					{
					DecrementDummyPPPMaxFailureCount();
					SendConfigReply(naklist, KPppLcpConfigNak);
					}
				break;
			case ERej:
				SendConfigReply(rejlist, KPppLcpConfigReject);
				break;
			default:
				break;
				}
			break;
		case KPppLcpConfigAck:
			//InitRestartCountForConfig();
			//CheckRecvConfigAck(rcvlist);
			//SetState(EDummyPPPFsmOpened);
			//As external option negotiation complete
			//iFlags |= KDummyPPPApplyPending; 
			break;
		case KPppLcpConfigNak:
		//Not responding to a reject
		//case KPppLcpConfigReject:
			SendConfigRequest();
			SetState(EDummyPPPFsmReqSent);
			break;
			}
		break;

	case EDummyPPPFsmAckSent:
		switch (iCodeRec)
			{
		case KPppLcpConfigRequest:
			switch (reply)
				{
			case EAck:
				SendConfigReply(acklist, KPppLcpConfigAck);
				break;
			case ENak:
				// RFC 1661 4.6
				if(CheckMaxFailureExceeded() == TRUE)
					SendConfigReply(naklist, KPppLcpConfigReject);
				else
					{
					DecrementDummyPPPMaxFailureCount();
					SendConfigReply(naklist, KPppLcpConfigNak);
					}
				SetState(EDummyPPPFsmReqSent);
				break;
			case ERej:
				SendConfigReply(rejlist, KPppLcpConfigReject);
				SetState(EDummyPPPFsmReqSent);
				break;
			default:
				break;
				}
			break;
		case KPppLcpConfigAck:
			InitRestartCountForConfig();
			CheckRecvConfigAck(rcvlist);
			SetState(EDummyPPPFsmOpened);
			//As external option negotiation complete
			iFlags |= KDummyPPPApplyPending; 
			break;
		case KPppLcpConfigNak:
			InitRestartCountForConfig();
			CheckRecvConfigNak(rcvlist, iDummyPPPRequestList);
			//SendConfigRequestAfterNak(rcvlist);
			SetNewId();
			SendConfigRequest();
			break;
		case KPppLcpConfigReject:
			//Not responding to a reject
			//InitRestartCountForConfig();
			//CheckRecvConfigReject(rcvlist, iDummyPPPRequestList);
			//SendConfigRequestAfterReject(rcvlist);
			//SetNewId();
			//SendConfigRequest();
			break;
			}
		break;

	case EDummyPPPFsmOpened:
		// Config Reset done above
		switch (iCodeRec)
			{
		case KPppLcpConfigRequest:
			SendConfigRequest();
			switch (reply)
				{
			case EAck:
				SendConfigReply(acklist, KPppLcpConfigAck);
				SetState(EDummyPPPFsmAckSent);
				break;
			case ENak:
				SendConfigReply(naklist, KPppLcpConfigNak);
				SetState(EDummyPPPFsmReqSent);
				break;
			case ERej:
				SendConfigReply(rejlist, KPppLcpConfigReject);
				SetState(EDummyPPPFsmReqSent);
				break;
			default:
				break;
				}
			break;
		case KPppLcpConfigAck:
			SendConfigRequest();
			CheckRecvConfigAck(rcvlist);
			SetState(EDummyPPPFsmReqSent);
			break;
		case KPppLcpConfigNak:
			CheckRecvConfigNak(rcvlist, iDummyPPPRequestList);
			//SendConfigRequestAfterNak(rcvlist);
			SetNewId();
			SendConfigRequest();
			SetState(EDummyPPPFsmReqSent);
			break;
		case KPppLcpConfigReject:
			//Not responding to the reject
			//CheckRecvConfigReject(rcvlist, iDummyPPPRequestList);
			//SendConfigRequestAfterReject(rcvlist);
			//SetNewId();
			//SendConfigRequest();
			//SetState(EDummyPPPFsmReqSent);
			break;
			}
		break;
		default:
			//Do nothing
		break; 
		}

	rcvlist.Free();	
	acklist.Free();
	naklist.Free();
	rejlist.Free();

	}
	
void CDummyPPPIf::ProcessPAPandIPCP()
	{
	CDummyNifLog::Printf(_L("Dummy PPP ProcessPAPandIPCP\r\n"));
	// Split the recvd packet into separate options
	// placing each option in a queue where it can be
	// easily parsed and manipulated in the upcall handlers.
	RPppOptionList rcvlist;	// Recvd list of options
	enum TDummyPPPResult { ENop, EAck, ENak, ERej };

	RPppOptionList acklist;	// List of Ack'd options - only valid of the following are empty
	RPppOptionList naklist;	// List of Nak'd options - only valid of the following is empty
	RPppOptionList rejlist;	// List of Rejected options


	TDummyPPPResult reply = ENop;

    TRAPD(err, rcvlist.SetL(ipktRecvPPP));
	if (err!=KErrNone)
		return;

	TInt iAction = ENop; 

	//For overriding PAP
	if (iDummyPPPState == EDummyPPPFsmOpened)
	{
		SetPppId(KPppIdIpcp);
		SetState(EDummyPPPFsmPapAckSent);
	}
	if(iDummyPPPState < EDummyPPPFsmPapAuthAckRecvd)
		{
		if (iDummyPPPState == EDummyPPPFsmOpened)
		{
			//Just for testing Nak packet
			//SendPapRequest();
			//SendPapNak(rcvlist);
			//SetState(EDummyPPPFsmPapAuthReqSent);
		}
			
		iAction = CheckRecvPapReq();
		reply = (iAction == KPppPapNak)?ENak:reply;
		reply = (iAction == KPppPapAck)?EAck:reply;
			
		}
	else
		CheckRecvIPCPReq(rcvlist, acklist, naklist, rejlist);

	if (!rejlist.IsEmpty())
		{
		reply = ERej;
		naklist.Free();
		acklist.Free();
		}
	else if (!naklist.IsEmpty())
		{
		reply = ENak;
		acklist.Free();
		}
	else if (!acklist.IsEmpty())
		{
		reply = EAck;
		//SetupConfigRequest(acklist);
		}
	 
	
	//Added to initialize the SendPPP index
	ipktRecvPPP.Pack();
	ptrTransPktPPP = &ipktRecvPPP;
	
	// State processing

	switch (iDummyPPPState)
		{
			case EDummyPPPFsmOpened:
				//Commenting Pap nego for the time being as PPP is rejecting it.
				//so skipping to IPCP Nego state
				//SetPppId(KPppIdPap);
				//SendPapRequest();
				//SetState(EDummyPPPFsmPapAuthReqSent);
				SetPppId(KPppIdIpcp);
				SetState(EDummyPPPFsmPapAckSent);

				break;
			case EDummyPPPFsmPapAuthAckRecvd:
					if(reply == EAck)
					{
						SendConfigReply(acklist, KPppLcpConfigAck);
						SetPppId(KPppIdIpcp);
						SetState(EDummyPPPFsmPapAckSent);
						break;
					}
					if(reply == ENak)
					{
						SendConfigReply(naklist, KPppLcpConfigNak);
						break;
					}
				break;
			case EDummyPPPFsmPapAckSent:
				if(iCodeRec == KPppLcpConfigRequest)
				{
					switch(reply)
					{
					case EAck:
						SendConfigReply(acklist, KPppLcpConfigAck);
						SetPppId(KPppIdIpcp);
						SendIPCPReq();
						SetState(EDummyPPPIPCPReqSent);
						break;
					case ENak:
					default:
						SetPppId(KPppIdIpcp);
						SendIPCPDummyNak();
						break;
					}
				}
				else
				{
					switch(reply)
					{
					case EAck:
						SetPppId(KPppIdIpcp);
						SendConfigReply(acklist, KPppLcpConfigAck);
						SetState(EDummyPPPFsmIPOpen);
						break;
					case ENak:
					default:
						SetPppId(KPppIdIpcp);
						SendIPCPDummyNak();
						break;
					}
				}
				break;
			case EDummyPPPIPCPReqSent:
				switch(reply)
					{
					case EAck:
						SendConfigReply(acklist, KPppLcpConfigAck);
						SetState(EDummyPPPFsmIPOpen);
						break;
				
					case ENak:
					default:
						SetPppId(KPppIdIpcp);
						SendIPCPReq();
						break;
					}
				break;
			default:
				//Do nothing
				break;
		}

	}

void CDummyPPPIf::ProcessTerminate()
	{
	if (iCodeRec==KPppLcpTerminateRequest)
		{
		switch (iDummyPPPState)
			{
		case EDummyPPPFsmInitial:
		case EDummyPPPFsmStarting:
			// bad event
			break;
		case EDummyPPPFsmClosed:
		case EDummyPPPFsmStopped:
		case EDummyPPPFsmClosing:
		case EDummyPPPFsmStopping:
			SendTerminateAck();
			break;
		case EDummyPPPFsmReqSent:
		case EDummyPPPFsmAckRecvd:
		case EDummyPPPFsmAckSent:
			iNotify->LinkLayerDown(KErrTimedOut, MNifIfNotify::EDisconnect);
			iLink->LinkDown(KErrCouldNotConnect);
			SendTerminateAck();
			SetState(EDummyPPPFsmReqSent);
			break;
		case EDummyPPPFsmOpened:
		case EDummyPPPFsmPapAuthReqSent:
		case EDummyPPPFsmPapAuthAckRecvd:
		case EDummyPPPFsmPapAckSent:
		case EDummyPPPIPCPReqSent:
			//SendTerminateAck();
		case EDummyPPPFsmIPOpen:
			// Fix for DEF002615
			// Dummy PPP should not convey KErrCommsLineFail to PPP when a Terminate Request 
			// is received. So blocking these two lines.
			//iLink->Stop(KErrCommsLineFail,MNifIfNotify::EDisconnect);
			//iLink->LinkDown(KErrCommsLineFail);
			iDummyPPPRestartCount = 0;
			SetState(EDummyPPPFsmInitial);
			break;
			}
		}
	else // KPppLcpTerminateAck
		{
			{
			switch (iDummyPPPState)
				{
			case EDummyPPPFsmInitial:
			case EDummyPPPFsmStarting:
				// bad event
				break;
			case EDummyPPPFsmClosed:
			case EDummyPPPFsmStopped:
				iLink->LinkDown(KErrCommsLineFail);
				iNotify->LinkLayerDown(KErrNone, MNifIfNotify::EDisconnect);
				break;
			case EDummyPPPFsmClosing:
				iLink->LinkDown(KErrCommsLineFail);
				SetState(EDummyPPPFsmClosed);
				break;
			case EDummyPPPFsmStopping:
				iLink->LinkDown(KErrCommsLineFail);
				SetState(EDummyPPPFsmStopped);
				iNotify->LinkLayerDown(KErrNone, MNifIfNotify::EDisconnect);
				break;
			case EDummyPPPFsmReqSent:
			case EDummyPPPFsmAckSent:
				break;
			case EDummyPPPFsmAckRecvd:
				SetState(EDummyPPPFsmReqSent);
				break;
			case EDummyPPPFsmOpened:
			case EDummyPPPFsmPapAuthReqSent:
			case EDummyPPPFsmPapAuthAckRecvd:
			case EDummyPPPFsmPapAckSent:
			case EDummyPPPIPCPReqSent:
			case EDummyPPPFsmIPOpen:
				iLink->Stop(KErrCommsLineFail,MNifIfNotify::EDisconnect);
				SendConfigRequest();
				SetState(EDummyPPPFsmReqSent);
				break;
				}
			}
		}

	}
void CDummyPPPIf::SetupSendPPP()
{	
	CDummyNifLog::Printf(_L("Dummy PPP SetupSendPPP\r\n"));
	if(ipktRecvPPP.IsEmpty())
	{
		
		//Storing data received into Recv Q
		iRecvQ.Append(ipktRecvPPP);
		//iSendNumBufs += ipktRecvPPP.NumBufs();
		
		iRecvQ.Remove(*ptrTransPktPPP);

		//ptrTransPktPPP = &ipktRecvPPP;

	}
}

void CDummyPPPIf::SendPapRequest()
	{
	 CDummyNifLog::Printf(_L("Dummy PPP SendPapRequest\r\n"));
#ifdef _UNICODE
	TBuf8<256> user,pass;

	//Only for testing
	//ConvertTo8Bit(user, iLink->UserName());
	//ConvertTo8Bit(pass, iProtocol->PassWord());
	
	user = _L8("EpochUser");
	pass = _L8("EpochPass");
	
#else
	TPtrC8 user, pass;
	user.Set(iProtocol->UserName());
	pass.Set(iProtocol->PassWord());
#endif

	RMBufPacket pkt;
	RMBufPktInfo* info = NULL;

	TInt len = 4+user.Length()+1+pass.Length()+1;
	TRAPD(err, pkt.AllocL(len));
	if (err!=KErrNone)
		return;
	TRAP(err, info = pkt.NewInfoL());
	if (err!=KErrNone)
		{
		pkt.Free();
		return;
		}
	TUint8* ptr = pkt.First()->Ptr();
	*ptr++ = KPppPapRequest;
	//Considering it as a New request
	//if (aNewRequest)
	//	{
		iDummyPPPTryCount = KDummyPPPPapRetries;
		if (++iCurrentDummyPPPId==0)
			++iCurrentDummyPPPId;
	//	}
	*ptr++ = iCurrentDummyPPPId;
	BigEndian::Put16(ptr, (TUint16)len);
	ptr += 2;
	*ptr++ = (TUint8)user.Length();	
	Mem::Copy(ptr, (TUint8*)user.Ptr(), user.Length());
	ptr += user.Length();
	*ptr++ = (TUint8)pass.Length();	
	Mem::Copy(ptr, (TUint8*)pass.Ptr(), pass.Length());
	ptr += pass.Length();
	info->iLength = len;	
	TPppAddr::Cast((info->iDstAddr)).SetProtocol(KPppIdPap);
	pkt.Pack();
	SendtoPPP(pkt);
	iLink->TimerCancel();
	iLink->TimerAfter(KDummyPPPPapWaitTime*1000);
	--iDummyPPPTryCount;

	}
void CDummyPPPIf::SendPapAck(RPppOptionList& aReplyList)
	{
	
	CDummyNifLog::Printf(_L("Dummy PPP SendPapAck\r\n"));
	RPppOption opt;
	RMBufPacket pkt;
	RPppOptionList iAckList;	// List of Ack'd options - only valid of the following are empty
 
	while (aReplyList.Remove(opt))
		{
		opt.OptType();
		iAckList.Append(opt);
		}
		
	TRAPD(err, iAckList.CreatePacketL(pkt, KPppIdPap, KPppPapAck, iIdRec));
	if (err==KErrNone)
		{
		SendtoPPP(pkt);
		}
	}
void CDummyPPPIf::SendPapNak(RPppOptionList& aReplyList)
	{
		
	CDummyNifLog::Printf(_L("SendPapNak\r\n"));
	RPppOption opt;
	RMBufPacket pkt;
	RMBufPacket* Packet;
	RPppOptionList iNakList;	// List of Nak'd options - only valid of the following is empty

	while (aReplyList.Remove(opt))
		{
		opt.OptType();
		iNakList.Append(opt);
		}
	TRAPD(err, iNakList.CreatePacketL(pkt, KPppIdPap, KPppPapNak, iIdRec));
	if (err==KErrNone)
		{
		Packet = (RMBufPacket*)&pkt;
		RMBufPktInfo*info = Packet->Unpack();
	    TPppAddr::Cast((info->iDstAddr)).SetProtocol(KPppIdPap);
		TPppAddr::Cast(info->iDstAddr).SetAddress(iLocalAddr);
		Packet->Pack();
		SendtoPPP(pkt);
		}
	}

TInt CDummyPPPIf::CheckRecvPapReq()
	{
		CDummyNifLog::Printf(_L("Dummy PPP CheckRecvPapReq\r\n"));
		switch (iCodeRec)
		{
		case KPppPapRequest:
			{
			TPtrC8 user;
			TPtrC8 pass;
			user.Set(&iCodeRec,sizeof(iCodeRec));   
			pass.Set(&iIdRec,sizeof(iIdRec));   
			}
			return 0;
		case KPppPapAck:
			if (iIdRec==iCurrentDummyPPPId)
			{
				iLink->TimerCancel();
				//Fix for DEF03548 Changing progress states to match that in pppprog.h
				iNotify->IfProgress(EPppProgressAuthenticationComplete,KErrNone);
				return KPppPapNak;
			}
			else
			{
				return KPppPapAck;
			}
		case KPppPapNak:
			if (iIdRec==iCurrentDummyPPPId)
			{
				iLink->TimerCancel();
				//Fix for DEF03548 Changing progress states to match that in pppprog.h
				iNotify->IfProgress(EPppProgressAuthenticationComplete,KErrIfAuthenticationFailure);
			}
			else
			{
				return KPppPapNak;
			}
		break;
		default:
			return KPppPapNak;
		}
		return KPppPapRequest;
	}
void CDummyPPPIf::SendIPCPDummyNak()
	{
		CDummyNifLog::Printf(_L("Dummy PPP SendIPCPDummyNak\r\n"));
		TRAPD(err, InitializeIPCPConfigRequestL());
		if (err==KErrNone)
		{
			if (iDummyPPPRequestList.IsEmpty())
			{
				CDummyNifLog::Printf(_L("Request list empty\r\n"));
				return;
			}

			RMBufPacket Packet;	
			//iDummyPPPRequestId = iIdRec;
			TRAPD(err, iDummyPPPRequestList.CreatePacketL(Packet, KPppIdIpcp, KPppLcpConfigNak, (TUint8)iIdRec));
			if (err!=KErrNone)
			{
				//__DEBUGGER();
				return;
			}
	
			ptrTransPktPPP = &Packet;

			RMBufPktInfo*info = Packet.Unpack();
		 
			TPppAddr::Cast((info->iDstAddr)).SetProtocol(KPppIdIpcp);
			TPppAddr::Cast(info->iDstAddr).SetAddress(iLocalAddr);
			Packet.Pack();

			SendtoPPP(*ptrTransPktPPP);
		}
	}
void CDummyPPPIf::InitializeIPCPConfigRequestL()
	{
	CDummyNifLog::Printf(_L("Dummy PPP InitializeIPCPConfigRequestL()\r\n"));
	SetNewId();
	InitRestartCountForConfig();
	
	if (!iDummyPPPRequestList.IsEmpty())
		iDummyPPPRequestList.Free();
	
	iDummyPPPRequestList.CreateAndAddL(KPppIpcpOptIpAddress, iLocalAddr);
	
	//BigEndian::Put32(opt.ValuePtr(), iRemoteAddr);
	//iDummyPPPRequestList.CreateAndAddL(KPppIpcpOptPrimaryDnsAddress, iPrimaryDns);
	//iDummyPPPRequestList.CreateAndAddL(KPppIpcpOptSecondaryDnsAddress, iSecondaryDns);

	}
void CDummyPPPIf::SendIPCPReq()
	{
		CDummyNifLog::Printf(_L("Dummy PPP SendIPCPReq\r\n"));
		TRAPD(err, InitializeIPCPConfigRequestL());
		if (err==KErrNone)
		{
			if (iDummyPPPRequestList.IsEmpty())
			{
				CDummyNifLog::Printf(_L("Request list empty\r\n"));
				return;
			}

			RMBufPacket Packet;	
			//iDummyPPPRequestId = iIdRec;
			TRAPD(err, iDummyPPPRequestList.CreatePacketL(Packet, KPppIdIpcp, KPppLcpConfigRequest, (TUint8)iIdRec));
			if (err!=KErrNone)
			{
			//__DEBUGGER();
				return;
			}
	
			ptrTransPktPPP = &Packet;

			RMBufPktInfo*info = Packet.Unpack();
		 
			TPppAddr::Cast((info->iDstAddr)).SetProtocol(KPppIdIpcp);
			TPppAddr::Cast(info->iDstAddr).SetAddress(iLocalAddr);
			Packet.Pack();

			SendtoPPP(*ptrTransPktPPP);
		}
	}
void CDummyPPPIf::CheckRecvIPCPReq(RPppOptionList& aRequestList, RPppOptionList& aAckList, RPppOptionList& aNakList, RPppOptionList& aRejList)
	{
	RPppOption opt;
	TUint8 temp;
	CDummyNifLog::Printf(_L("Dummy PPP CheckRecvIPCPReq\r\n"));
	while (aRequestList.Remove(opt))
		{
		temp = opt.OptType();
		switch (temp)
			{
		case KPppIpcpOptIpAddress:
			{
			TUint32 addr = BigEndian::Get32(opt.ValuePtr());
			if (addr==0)
				{
					aNakList.Append(opt);
				}
			else
				aAckList.Append(opt);
			}
			break;
		case KPppIpcpOptIpAddresses:
         {
			TUint32 remoteAddr = BigEndian::Get32(opt.ValuePtr());
			TUint32 addr = BigEndian::Get32(opt.ValuePtr()+4);

         if (remoteAddr == 0)
            {
				aRejList.Append(opt);
            }
         else if (addr == 0)
            {
				aNakList.Append(opt);
				}
			else
            {
				iRemoteAddr = remoteAddr;
				aAckList.Append(opt);
            }
         }
		 break;
			}
		}
	}

void CDummyPPPIf::SetState(TDummyPPPToPPPFsmState aState)
	{
	CDummyNifLog::Write(_L("DummyPPP::SetState()"));

	_LIT(KStateString,"State %s -> %s");


	CDummyNifLog::Printf(KStateString,CDummyNifLog::StateToText(iDummyPPPState), CDummyNifLog::StateToText(aState));

	iDummyPPPState = aState;
	}
void CDummyPPPIf::SetPppId(TUint aProt)
	{
	CDummyNifLog::Printf(_L("DummyPPP::SetPppId to %d\n"),aProt);
	iSendPppId = aProt;
	}

void CDummyPPPIf::InitRestartCountForConfig()
	{
	CDummyNifLog::Printf(_L("Dummy PPP InitRestartCountForConfig\r\n"));
	// RFC 1661 4.6 Max-Configure
	iDummyPPPWaitTime = KDummyPPPWaitTimeConfig;
	iDummyPPPRestartCount = KDummyPPPMaxRestartConfig;
	}

void CDummyPPPIf::SetNewId()
	{
	TUint8 id = ++iCurrentDummyPPPId;
	if (iCurrentDummyPPPId==0)
		++iCurrentDummyPPPId;
	iDummyPPPRequestId = id;
	CDummyNifLog::Printf(_L("Dummy PPP SetNewId %d\r\n"),iDummyPPPRequestId);
	}

void CDummyPPPIf::InitialiseConfigRequestL()
	{
	TUint32 iDummyPPPRecvEscMap = 0;
	SetNewId();
	InitRestartCountForConfig();
	SetPppId(KPppIdLcp);
	
	CDummyNifLog::Printf(_L("Dummy PPP InitialiseConfigRequest\r\n"));
	if (!iDummyPPPRequestList.IsEmpty())
		iDummyPPPRequestList.Free();
	
	// Create a new magic number
	iPPPRemMagicNumber = 0;
	
	if (iDummyPPPLocMagicNumber == 0)
	{
		//CPppLcp::NewMagicNumber(iDummyPPPLocMagicNumber);
		//Only for testing
		iDummyPPPLocMagicNumber = 54321;
	}
	
	iDummyPPPRequestList.CreateAndAddL(KPppLcpOptMagicNumber, (TUint32)iDummyPPPLocMagicNumber);
	if ((iOrigConfig().iHandshake & KConfigSendXoff)!=0
		|| (iOrigConfig().iHandshake & KConfigSendXoff)!=0)
		{
		if (iOrigConfig().iXonChar<32)
			iDummyPPPRecvEscMap |= 1<<iOrigConfig().iXonChar;
		if (iOrigConfig().iXoffChar<32)
			iDummyPPPRecvEscMap |= 1<<iOrigConfig().iXoffChar;
		}
	//for testing options
	//iDummyPPPRequestList.CreateAndAddL(KPppLcpOptEscapeCharMap,iDummyPPPRecvEscMap);
	//iDummyPPPRequestList.CreateAndAddL(KPppLcpOptProtocolCompress);
	//iDummyPPPRequestList.CreateAndAddL(KPppLcpOptAddrCtrlCompress);

	}

void CDummyPPPIf::SetupConfigRequest(RPppOptionList& aRequestList)
//
// Apply options in a recvd config request (that was ACK'd)
//
	{
	CDummyNifLog::Printf(_L("Dummy PPP SetupConfigRequest\r\n"));
	TMBufPktQIter iter(aRequestList);
	RPppOption opt;

	while (opt = iter++, !opt.IsEmpty())
		{
		switch (opt.OptType())
			{
		case KPppLcpOptMaxRecvUnit:
			//iMaxSendSize = BigEndian::Get16(opt.ValuePtr());
			break;
		case KPppLcpOptMagicNumber:
			iPPPRemMagicNumber = BigEndian::Get32(opt.ValuePtr());
			break;
		default:
			//ExtOptApplyConfigRequest(opt);
			break;
			}
		}
	}

void CDummyPPPIf::CheckRecvConfigRequest(RPppOptionList& aRequestList, RPppOptionList& aAckList, RPppOptionList& aNakList, RPppOptionList& aRejList)
//
// Check options in a recvd config request
//
	{
	CDummyNifLog::Printf(_L("Dummy PPP CheckRecvConfigRequest\r\n"));
	RPppOption opt;
	//only for debugging
	TUint8 temp;

	while (aRequestList.Remove(opt))
		{
		temp = opt.OptType();
		switch (temp)
			{
		case KPppLcpOptMaxRecvUnit:
			if (opt.ValueLength()<0)
				aNakList.Append(opt);
			else
				{
				if (opt.ValueLength()<2)
					aRejList.Append(opt);
				else
					aAckList.Append(opt);
				}
			break;

		case KPppLcpOptMagicNumber:
			if (opt.ValueLength()<0)
				aNakList.Append(opt);
			else
				{
				if (opt.ValueLength()!=4)
					aRejList.Append(opt);
				else
					{
					iPPPRemMagicNumber = BigEndian::Get32(opt.ValuePtr());
					if (iPPPRemMagicNumber!=iDummyPPPLocMagicNumber)
						{
						aAckList.Append(opt);
						}
					else
						{
						//CPppLcp::NewMagicNumber(iPPPRemMagicNumber);
						//Only for testing
						iPPPRemMagicNumber = 11111;
						BigEndian::Put32(opt.ValuePtr(), iPPPRemMagicNumber);
						aNakList.Append(opt);
						}
					}
				}
			break;
		case KPppLcpOptMultiLinkEndPointDescriminator:
	        aAckList.Append(opt);
			break;

		default:
			//ExtOptCheckConfigRequest(aPacket, (CProtocolBase*)this);
    		iPppOptions->ExtOptCheckConfigRequest(opt, aAckList, aNakList, aRejList);
			}
		}
	}

void CDummyPPPIf::CheckRecvConfigAck(RPppOptionList& aReplyList)
//
// Recvd a Config Ack - apply the options
//
	{
	CDummyNifLog::Printf(_L("Dummy PPP CheckRecvConfigAck\r\n"));
	TMBufPktQIter iter(aReplyList);
	RPppOption opt;
		
	while (opt = iter++, !opt.IsEmpty())
		{
		switch (opt.OptType())
			{
		case KPppLcpOptMaxRecvUnit:
			//iMaxRecvSize = BigEndian::Get16(opt.ValuePtr());
			break;
		case KPppLcpOptMagicNumber:
			// Magic number is OK
			//SendDummyPPPIdentification();
			break;
		default:
			iPppOptions->ExtOptRecvConfigAck(opt);
			break;
			}
		}
	}

void CDummyPPPIf::CheckRecvConfigNak(RPppOptionList& aReplyList, RPppOptionList& aReqList)
//
// Recvd a Config Nak - The associated original request is in aReqList
//
	{
	CDummyNifLog::Printf(_L("DummyPPP::CheckRecvConfigNak\r\n"));
	TMBufPktQIter iter(aReplyList);
	RPppOption opt;
	
	while (opt = iter++, !opt.IsEmpty())
		{
		switch (opt.OptType())
			{
		case KPppLcpOptMaxRecvUnit:
			aReqList.ReplaceOption(opt);
			break;
		case KPppLcpOptMagicNumber:
			{
			iDummyPPPLocMagicNumber = BigEndian::Get32(opt.ValuePtr());
			aReqList.ReplaceOption(opt);
			}
			break;
		default:
			iPppOptions->ExtOptRecvConfigNak(opt, aReqList);
			break;
			}
		}
	}

void CDummyPPPIf::CheckRecvConfigReject(RPppOptionList& aReplyList, RPppOptionList& aReqList)
//
// Recvd a Config Reject - The associated original request is in aReqList
//
	{
	TMBufPktQIter iter(aReplyList);
	RPppOption opt;
	CDummyNifLog::Printf(_L("Dummy PPP CheckRecvConfigReject\r\n"));
	
	while (opt = iter++, !opt.IsEmpty())
		{
		switch (opt.OptType())
			{
		case KPppLcpOptMaxRecvUnit:
			aReqList.RemoveOption(opt);
			break;
		case KPppLcpOptMagicNumber:
			aReqList.RemoveOption(opt);
			break;
		default:
			iPppOptions->ExtOptRecvConfigReject(opt, aReqList);
			break;
			}
		}
	}


void CDummyPPPIf::SendConfigRequest()
//
// Send the config request in iDummyPPPRequestList
//
	{

	if (iDummyPPPRequestList.IsEmpty())
		{
		CDummyNifLog::Write(_L("DummyPPP Request list empty\r\n"));
		return;
		}

	CDummyNifLog::Printf(_L("Dummy PPP SendConfigRequest\r\n"));
	RMBufPacket pkt;	
	iDummyPPPRequestId &= 0xff;
	TRAPD(err, iDummyPPPRequestList.CreatePacketL(pkt, iSendPppId, KPppLcpConfigRequest, (TUint8)iDummyPPPRequestId));
	if (err==KErrNone)
		{
		SendtoPPP(pkt);
		--iDummyPPPRestartCount;
		iLink->TimerCancel();
		TInt temp=iDummyPPPWaitTime;
		iLink->TimerAfter(iDummyPPPWaitTime*1000);
		iDummyPPPWaitTime=temp;
		}	
	}

void CDummyPPPIf::SendConfigReply(RPppOptionList& aOptList,TUint8 aType)
	{
	RMBufPacket pkt;
	CDummyNifLog::Printf(_L("Dummy PPP SendConfigReply\r\n"));
	TRAPD(err, aOptList.CreatePacketL(pkt, iSendPppId, aType, iIdRec));
	if (err==KErrNone)
		{
		SendtoPPP(pkt);
		iLink->TimerCancel();
		TInt temp=iDummyPPPWaitTime;
		iLink->TimerAfter(iDummyPPPWaitTime*1000);
		iDummyPPPWaitTime=temp;
		}
	}

void CDummyPPPIf::SendTerminateAck()
	{
	RMBufPacket pkt;
	RMBufPktInfo* info=NULL;
	CDummyNifLog::Printf(_L("Dummy PPP SendTerminateAck\r\n"));
	TRAPD(err, pkt.AllocL(4));
	if (err ==KErrNone)
		{
		TRAP(err,info = pkt.NewInfoL());
		}
	if (err ==KErrNone)
		{
		info->iLength = 4;
		TPppAddr::Cast((info->iDstAddr)).SetProtocol(iSendPppId);
		TUint8* ptr = pkt.First()->Ptr();
		*ptr++ = KPppLcpTerminateAck;
		*ptr++ = iIdRec;
		BigEndian::Put16(ptr, (TUint16)4);
		pkt.Pack();
		SendtoPPP(pkt);
		}
	else
		{
		pkt.Free();
		__ASSERT_DEBUG(EFalse,User::Invariant());
		}
	}

void CDummyPPPIf::SendDummyPPPIdentification()
	{

	CDummyNifLog::Printf(_L("Dummy PPP SendDummyPPPIdentification\r\n"));
	TInt err;
	TPtrC8 id = _L8("Symbian Epoc!");
	RMBufPacket pkt;
	RMBufPktInfo* info = NULL;
	TRAP(err, info = pkt.NewInfoL());
	if (err!=KErrNone)
		return;
	info->iLength = 4+4+id.Length();
	TRAP(err, pkt.AllocL(info->iLength));
	if (err!=KErrNone)
		{
		pkt.FreeInfo();
		return;
		}
	TUint8* ptr = pkt.First()->Ptr();
	*ptr++ = (TUint8)KPppLcpIdentification;
	SetNewId();
	*ptr++ = iDummyPPPRequestId;
	BigEndian::Put16(ptr, (TUint16)info->iLength);
	BigEndian::Put32(ptr+2, (TUint32)iDummyPPPLocMagicNumber);
	pkt.CopyIn(id, 8);
	pkt.Pack();
	SendtoPPP(pkt);
	}
TInt CDummyPPPLink::Start()
	{
	CDummyNifLog::Printf(_L("Dummy PPP Link::Start\r\n"));
	
	//As CreateL is not called before Start calling it here
	TRAPD(err, iNifIf->CreateL());
	if (err != KErrNone)
		return err;
	iState = EDummyPPPLinkOpen;
 
	iNotify->IfProgress(KLinkLayerOpen, KErrNone);
	iNotify->LinkLayerUp();

	iNifIf->OpenFSM();
	iNifIf->InitRestartCountForConfig();
	//Setting iSendFlowOn to start
	iNifIf->SetFlowOnFlag(ETrue);
	iNifIf->iProtocol->StartSending((CProtocolBase*)iNifIf);
	
	return KErrNone;
	}
void CDummyPPPIf::CloseFSM()
	{
	CDummyNifLog::Printf(_L("Dummy PPP Close FSM Request\r\n"));
	
	//Setting response to PPP state machine
	if((iDummyPPPState == EDummyPPPFsmInitial)
		||(iDummyPPPState == EDummyPPPFsmStarting))
		{
		//Do nothing
		}
	if((iDummyPPPState == EDummyPPPFsmClosed)
		||(iDummyPPPState == EDummyPPPFsmClosing))
		{
		SetState(EDummyPPPFsmInitial);
		}
    if((iDummyPPPState == EDummyPPPFsmStopped)
		||(iDummyPPPState == EDummyPPPFsmStopping)
		||(iDummyPPPState == EDummyPPPFsmReqSent)
		||(iDummyPPPState == EDummyPPPFsmAckRecvd)
		||(iDummyPPPState == EDummyPPPFsmAckSent)
		||(iDummyPPPState == EDummyPPPFsmOpened))
		{
		SetState(EDummyPPPFsmStarting);
		}
}
void CDummyPPPIf::ChangeStateforTimerComplete()
	{
	
	CDummyNifLog::Printf(_L("Dummy PPP Timer Expired %d \r\n"),iDummyPPPRestartCount);
	if((iDummyPPPState == EDummyPPPFsmInitial)
		||(iDummyPPPState == EDummyPPPFsmStarting)
		||(iDummyPPPState == EDummyPPPFsmClosed)
		||(iDummyPPPState == EDummyPPPFsmStopped)
		||(iDummyPPPState == EDummyPPPFsmOpened))
		// Bad Event
		return;
   
	if (iDummyPPPRestartCount>0)
		{
		switch (iDummyPPPState)
			{
		case EDummyPPPFsmClosing:
		case EDummyPPPFsmStopping:
			//SendTerminateRequest();
			break;
		case EDummyPPPFsmReqSent:
		case EDummyPPPFsmAckRecvd:
		case EDummyPPPFsmAckSent:
			//PG RFC 1661 4.6 double timeout period
			//if (iDummyPPPWaitTime*2<KDummyPPPFsmRequestMaxTimeout)
			//	iDummyPPPWaitTime = iDummyPPPWaitTime*2;
			//SendConfigRequest();
			
			//if(iDummyPPPState == EDummyPPPFsmAckRecvd)
			//	SetState(EDummyPPPFsmReqSent);
			break;
		default:
			break;
			}
		}
	else
		{
	
		switch (iDummyPPPState)
			{
		case EDummyPPPFsmClosing:
			SetState(EDummyPPPFsmClosed);
			break;
		case EDummyPPPFsmStopping:
		case EDummyPPPFsmReqSent:
		case EDummyPPPFsmAckRecvd:
		case EDummyPPPFsmAckSent:
			SetState(EDummyPPPFsmStopped);
			break;
		default:
			break;
			}
		}

	if (iDummyPPPTryCount>0)
		SendPapRequest();
	}

void CDummyPPPLink::TimerComplete(TInt)
	{

	CDummyNifLog::Write(_L("DummyPPP Link::TimerComplete()"));

	//
	// Upcall from Timer
	//
    iNifIf->ChangeStateforTimerComplete();

	//Here while closing down it crashes!
	//iNifIf->CloseFSM();
    //iNotify->LinkLayerDown(KErrTimedOut, MNifIfNotify::EDisconnect);
	
	}


void CDummyPPPLink::Stop(TInt aError, MNifIfNotify::TAction aAction)		
	{
	switch (iState)
		{
	case EDummyPPPLinkClosed:
		return;
	case EDummyPPPLinkConnecting:
		iState = EDummyPPPLinkClosed;
		break;
	case EDummyPPPLinkOpen:
		//iNifIf->PacketModeOff();
		iState = EDummyPPPLinkClosed;
		break;
	default:
		break;
		}
	CDummyNifLog::Printf(_L("DummyPPP Link::Stop(aError %d, TAction %d)"), aError, aAction);
	//Commenting as this has to be conveyed by PPP and not DummyPPP Nif
	//iNotify->IfProgress(KLinkLayerClosed, aError);
	iNifIf->CloseFSM();
	//Commenting as this has to be conveyed by PPP and not DummyPPP Nif
	iNotify->LinkLayerDown(aError, aAction);
	
	}

void CDummyPPPLink::IfProgress(TInt /*aResult*/)
	{
	}
void CDummyPPPIf::BindL(TAny *aId)
	{
	CDummyNifLog::Printf(_L("BindL(aId %x)\r\n"),aId);
	if (iProtocol)
		User::Leave(KErrAlreadyExists);
	iProtocol = (CProtocolBase*)aId;
	}

void CDummyPPPIf::SetFlowOnFlag(TBool aFlag)
	{
		CDummyNifLog::Printf(_L("Dummy PPP SetFlowOnFlag\r\n"));
		iSendFlowOn = aFlag;
	}

CNifIfBase* CDummyPPPLink::GetBinderL(const TDesC& aName)
	{
	CDummyNifLog::Printf(_L("DummyPPP LinkGetBinderL(%S)"), &aName);

	iNifIf = new(ELeave) CDummyPPPIf(this);
	return iNifIf;

	}

TInt CDummyPPPLink::Notification(TAgentToNifEventType aEvent,void* aInfo)
	{
	CDummyNifLog::Printf(_L("Dummy PPP LinkNotification\r\n"));
	if ((aEvent!=EAgentToNifEventTypeDisableTimers) 
		|| (aInfo!=NULL))
		return KErrUnknown;
	return KErrNone;
	}

void CDummyPPPLink::Restart(CNifIfBase*)
	{}

CDummyPPPIf::CDummyPPPIf(CDummyPPPLink* aLink)
	: CNifIfBase(*aLink)
	{
	CDummyNifLog::Printf(_L("DummyPPP Constructed"));

	//__DECLARE_FSM_NAME(_S("DUMMY_PPP FSM"));

	iLink = aLink;
	
	//Settings for flow control
	iSendLoWat = KLoWatMark;
	iSendHiWat = KHiWatMark;

	// generate my local ip address (ip4) - vals potentially will be overwritten by any derived classes
	iLocalAddress = KDummyPppNifLocalAddressBase;//0x0A220C1BB; //+ ((TUint32)this)%255;
    
	//For IPCP Nego.
	//PresetAddr(iLocalAddr, TPtrC(KCDTypeNameIpAddr));
	iLocalAddr = iLocalAddress;

	//PresetAddr(iPrimaryDns, TPtrC(KCDTypeNameIpNameServer1));
	//PresetAddr(iSecondaryDns, TPtrC(KCDTypeNameIpNameServer2));
	//iPrimaryNbns = IPADDR(0,0,0,0);
	//iSecondaryNbns = IPADDR(0,0,0,0);
	//PresetAddr(iNetworkMask, TPtrC(KCDTypeNameIpNetMask));

	// need to give each if a unique id so we will number and count them as we create them
	//++iNumOfIfs;
	//iIfNum = iNumOfIfs;

	//Even if this is given, when the identification command for the nif is given
	//it always turns up as a ipcp.comm as PPP Nif gives the information overlooking this.
	iIfName.Format(_L("dummypppnif[0x%08x]"), this);



	}
TInt CDummyPPPIf::PresetAddr(TUint32& aAddr, const TDesC& aVarName)
/**
 * Preset IP adress in aAddr with value from CommDB. The field name
 * is given in aVarName. Examples are "IpAddr" and "IpNameServer1"
 *
 * @param aAddr    IP address to be set
 * @param aVarName name of CommDB field
 * @return KErrNone if success, global error code otherwise
 */
	{
	if (aAddr!=0)
		return KErrNone;
	
	TBuf<KCommsDbSvrMaxFieldLength> name;
	TInetAddr addr;
    

	(void)iNotify->ReadDes(aVarName, name); // ignore return value

	const TInt ret = addr.Input(name);
	if (ret==KErrNone)
		aAddr = addr.Address();

	return ret;
	}


void CDummyPPPIf::Info(TNifIfInfo& aInfo) const
	{
	CDummyNifLog::Printf(_L("Dummy PPP Info\r\n"));
	aInfo.iVersion = TVersion(1,1,1);
	aInfo.iFlags = KNifIfIsBase | KNifIfUsesNotify | KNifIfCreatedByLink;
	aInfo.iName.Copy(iIfName);
	aInfo.iProtocolSupported = 0;
	}

void CDummyPPPLink::FillInInfo(TNifIfInfo& aInfo, TAny* aPtr)
	{
	aInfo.iProtocolSupported=0;
	aInfo.iVersion = TVersion(1,1,1);
	aInfo.iFlags = KNifIfIsBase | KNifIfIsLink | KNifIfUsesNotify | KNifIfCreatedByFactory;
    aInfo.iName = _L("dummyppplink");
	aInfo.iName.AppendFormat(_L("[0x%08x]"), aPtr);
	aInfo.iFlags |= KNifIfCreatesBinder;
	}

void CDummyPPPLink::Info(TNifIfInfo& aInfo) const
	{
	FillInInfo(aInfo,(TAny*) this);
	CDummyNifLog::Printf(_L("Dummy PPP LinkInfo\r\n"));
	}

TInt CDummyPPPIf::Control(TUint aLevel, TUint aName, TDes8& aOption, TAny* /* aSource */)
	{
	CDummyNifLog::Printf(_L("DummyPPP::Control(aLevel %x, aName %x, ...)"), aLevel, aName);

	if (aLevel==KSOLInterface)
		{
		switch (aName)
			{
		case KSoIfInfo:
			{
			TSoIfInfo& opt = *(TSoIfInfo*)aOption.Ptr();

			_LIT(KName, "MyName");
			opt.iName.Copy(KName);
			opt.iFeatures = KIfCanBroadcast | KIfCanMulticast;
			opt.iMtu = 1500;
			opt.iSpeedMetric = 0;
			return KErrNone;
			}

		case KSoIfHardwareAddr:
			return KErrNotSupported;

		case KSoIfConfig:
			{
			TSoInetIfConfig& opt = *(TSoInetIfConfig*)aOption.Ptr();
			if (opt.iFamily!=KAfInet)
				return KErrNotSupported;

			TUint32 address;
			const TInt KPort = 65;

			opt.iConfig.iAddress.SetAddress(iLocalAddress);
			opt.iConfig.iAddress.SetPort(KPort);

			// network mask
			opt.iConfig.iNetMask.Input(KNetworkMask);
			opt.iConfig.iNetMask.SetPort(KPort);

			// broadcast address
			address = KDummyPppNifLocalAddressBase + KBroadcastAddressSuffix;
			opt.iConfig.iBrdAddr.SetAddress(address);
			opt.iConfig.iBrdAddr.SetPort(KPort);

			// default gateway
			address = KDummyPppNifLocalAddressBase + KDefaultGatewayAddressSuffix;
			opt.iConfig.iDefGate.SetAddress(address);
			opt.iConfig.iDefGate.SetPort(KPort);

			// primary DNS, just make same as default gateway
			opt.iConfig.iNameSer1.SetAddress(address);
			opt.iConfig.iNameSer1.SetPort(KPort);

			// secondary DNS
			address = KDummyPppNifLocalAddressBase + KSecondaryDnsAddressSuffix;
			opt.iConfig.iNameSer2.SetAddress(address);
			opt.iConfig.iNameSer2.SetPort(KPort);

			return KErrNone;
			}

		case KSoIfGetConnectionInfo:
			TSoIfConnectionInfo& opt = *(TSoIfConnectionInfo*)aOption.Ptr();
			TInt err = KErrNone;
			TBuf<2*KCommsDbSvrMaxColumnNameLength+1> fieldName;
			_LIT(KSlashChar, "\\");

			fieldName.Copy(TPtrC(KCDTypeNameIAP));
			fieldName.Append(KSlashChar);
			fieldName.Append(TPtrC(KCDTypeNameRecordTag));
			if ((err = iNotify->ReadInt(fieldName, opt.iIAPId)) != KErrNone)
				return err;

			fieldName.Copy(TPtrC(IAP));
			fieldName.Append(KSlashChar);
			fieldName.Append(TPtrC(KCDTypeNameIAPNetwork));
			if ((err = iNotify->ReadInt(fieldName, opt.iNetworkId)) != KErrNone)
				return err;

			return KErrNone;
			}
		}
	return KErrNotSupported;
	}

TInt CDummyPPPIf::Notification(TAgentToNifEventType /*aEvent*/, void * /*aInfo*/)
	{
	CDummyNifLog::Printf(_L("Dummy PPP Notification\r\n"));	
	return KErrNone;
	}

void CDummyNifLog::Write(const TDesC& aDes)
//
// Write aText to the log
//
	{	
#ifndef __FLOG_ACTIVE
	(void)aDes;
#else
	__FLOG_STATIC0(KDummyPppLogFolder, KDummyPppLogFile, aDes);
#endif
	}
 
void CDummyNifLog::Printf(TRefByValue<const TDesC> aFmt,...)
//
// Write a mulitple argument list to the log, trapping and ignoring any leave
//
	{
#ifndef __FLOG_ACTIVE
	(void)aFmt;
#else
	VA_LIST list;
	VA_START(list, aFmt);

	TBuf <1024> LineBuf;
	LineBuf.AppendFormatList( aFmt, list);

	__FLOG_STATIC0(KDummyPppLogFolder, KDummyPppLogFile, LineBuf);
#endif // #ifdef __FLOG_ACTIVE
	}

void CDummyNifLog::HexDump(const TText* aHeader, const TText* aMargin, const TUint8* aPtr, TInt aLen, TInt aWidth)
	{
	TBuf<0x100> buf;
	TInt i = 0;
	const TText* p = aHeader;
	while (aLen>0)
		{
		TInt n = aLen>aWidth ? aWidth : aLen;
		if (p!=NULL)
			{
			_LIT(string1,"%s%04x : ");
			buf.AppendFormat(string1, p, i);
			}
		TInt j;
		_LIT(string2,"%02x ");
		for (j=0; j<n; j++)
			buf.AppendFormat(string2, aPtr[i+j]);
		_LIT(string3,"   ");
		while (j++<KHexDumpWidth)
			buf.Append(string3);
		_LIT(string4," ");
		buf.Append(string4);
		_LIT(string5,"%c");
		for (j=0; j<n; j++)
			buf.AppendFormat(string5, aPtr[i+j]<32 || aPtr[i+j]>126 ? '.' : aPtr[i+j]);
		buf.Append(KEndOfLine);
		Write(buf);
		buf.SetLength(0);
		aLen -= n;
		i += n;
		p = aMargin;
		}
	}



void CDummyPPPIf::CreateL()
	{
	CDummyNifLog::Printf(_L("Dummy PPP CreateL"));
	logUser = new(ELeave) CDummyNifLog;
	TCallBack scb(SendCallBack, this);	
	iSendCallBack = new(ELeave) CAsyncCallBack(scb, KDummyPPPSendPriority);
	}

void CDummyPPPIf::OpenFSM()
{
	logUser->Printf(_L("Open FSM Request\r\n"));
	
	iDummyPPPMaxFailureCount = KDummyPPPMaxRestartConfig;
	
	if(iDummyPPPState == EDummyPPPFsmInitial)
	{
		SetState(EDummyPPPFsmStarting);
		TRAPD(err, InitialiseConfigRequestL());
		if (err==KErrNone)
			SendConfigRequest();
		SetState(EDummyPPPFsmReqSent);
	}
}

void CDummyPPPIf::CloseLog()
	{	
	logUser->Printf(_L("Dummy PPP CloseLog\r\n"));	
	delete logUser;
	}
void CDummyPPPIf::End()
	{
	CDummyNifLog::Printf(_L("Dummy PPP End\r\n"));	
	ipktRecvPPP.Free();
	delete iSendCallBack;
	iSendCallBack = NULL;
	}

//The following code is for logs only
const TText* CDummyNifLog::StateToText(TDummyPPPToPPPFsmState aState)
	{

	// States
	switch (aState)
		{
	case EDummyPPPFsmInitial:
		return _S("INITIAL");
	case EDummyPPPFsmStarting:
		return _S("STARTING");
	case EDummyPPPFsmClosed:
		return _S("CLOSED");
	case EDummyPPPFsmStopped:
		return _S("STOPPED");
	case EDummyPPPFsmStopping:
		return _S("STOPPING");
	case EDummyPPPFsmClosing:
		return _S("CLOSING");
	case EDummyPPPFsmReqSent:
		return _S("REQUEST SENT");
	case EDummyPPPFsmAckRecvd:
		return _S("ACK RECEIVED");
	case EDummyPPPFsmAckSent:
		return _S("ACK SENT");
	case EDummyPPPFsmOpened:
		return _S("OPENED");
	case EDummyPPPFsmPapAuthReqSent:
		return _S("PAP REQUEST SENT");
	case EDummyPPPFsmPapAuthAckRecvd:
		return _S("PAP ACK RECEIVED");
	case EDummyPPPFsmPapAckSent:
		return _S("PAP ACK SENT");
	case EDummyPPPIPCPReqSent:
		return _S("IPCP REQUEST SENT");
	case EDummyPPPFsmIPOpen:
		return _S("IP OPENED");
	default:	// Should never happen in theory!
		return _S("UNKNOWN");
		}
	}


const TText* CDummyNifLog::LcpCodeToText(TUint aValue)
	{

	// LCP Codes
	switch (aValue)
		{
	case KPppLcpEchoRequest:
		return _S("Echo request");
	case KPppLcpEchoReply:
		return _S("Echo reply");
	case KPppLcpDiscardRequest:
		return _S("Discard request");
	case KPppLcpIdentification:
		return _S("Identification");
	case KPppLcpTimeRemaining:
		return _S("Time remaining");
	default:
		return FsmCodeToText(aValue);
		}
	}

const TText* CDummyNifLog::FsmCodeToText(TUint aValue)
	{

	// LCP Codes
	switch (aValue)
		{
	case KPppLcpConfigRequest:
		return _S("Config Request");
	case KPppLcpConfigAck:
		return _S("Config ACK");
	case KPppLcpConfigNak:
		return _S("Config NAK");
	case KPppLcpConfigReject:
		return _S("Config Reject");
	case KPppLcpTerminateRequest:
		return _S("Terminate request");
	case KPppLcpTerminateAck:
		return _S("Terminate ACK");
	case KPppLcpCodeReject:
		return _S("Code Reject");
	case KPppLcpProtocolReject:
		return _S("Protocol Reject");
	case KPppCcpResetReq:
		// Only used by CCP, but this is the easiest place to put it
		return _S("Reset Request");
	case KPppCcpResetAck:
		// Only used by CCP, but this is the easiest place to put it
		//__DEBUGGER();
		return _S("Reset Ack");
	default:
		return _S("Unknown");
		}
	}

const TText* CDummyNifLog::PapCodeToText(TUint aValue)
	{

	// PAP Codes
	switch (aValue)
		{
	case 1:
		return _S("Authenticate Request");
	case 2:
		return _S("Authenticate ACK");
	case 3:
		return _S("Authenticate NAK");
	default:
		return _S("Unknown");
		}
	}

const TText* CDummyNifLog::CbcpCodeToText(TUint aValue)
	{

	// CHAP Codes
	switch (aValue)
		{
	case 1:
		return _S("Callback Request");
	case 2:
		return _S("Callback Response");
	case 3:
		return _S("Callback Ack");
	default:
		return _S("Unknown");
		}
	}

const TText* CDummyNifLog::ChapCodeToText(TUint aValue)
	{

	// CHAP Codes
	switch (aValue)
		{
	case 1:
		return _S("Challenge");
	case 2:
		return _S("Response");
	case 3:
		return _S("Success");
	case 4:
		return _S("Failure");
	default:
		return _S("Unknown");
		}
	}

const TText* CDummyNifLog::IpProtocolToText(TUint aValue)
	{

	// IP Protocols
	switch (aValue)
		{
	case 1:
		return _S("ICMP");
	case 58:
		return _S("ICMPv6");
	case 17:
		return _S("UDP");
	case 6:
		return _S("TCP");

	default:
		return _S("Unknown");
		}
	}

const TText* CDummyNifLog::IpcpCodeToText(TUint aValue)
	{

	// IPCP Codes
	switch (aValue)
		{
	case KPppIpcpOptIpAddresses:
		return _S("IP Addresses");
	case KPppIpcpOptIpCompressionProtocol:
		return _S("IP Compression Protocol");
	case KPppIpcpOptIpAddress:
		return _S("IP Address");
	case KPppIpcpOptPrimaryDnsAddress:
		return _S("Primary DNS Address");
	case KPppIpcpOptSecondaryDnsAddress:
		return _S("Secondary DNS Address");
	case KPppIpcpOptPrimaryNbnsAddress:
		return _S("Primary NBNS Address");
	case KPppIpcpOptSecondaryNbnsAddress:
		return _S("Secondary NBNS Address");
	default:
		return _S("Unknown");
		}
	}

const TText* CDummyNifLog::Ip6cpCodeToText(TUint aValue)
	{
	// IP6CP Codes
	switch (aValue)
		{
	case KPppIp6cpOptInterfaceIdentifier:
		return _S("Interface Identifier");
	case KPppIp6cpOptCompressionProtocol:
		return _S("Compression Protocol");
	default:
		return _S("Unknown");
		}
	}
const TText* CDummyNifLog::CcpCodeToText(TUint aValue)
	{

	// CCP Codes
	switch (aValue)
		{
	case KPppCcpOptOui:
		return _S("OUI");
	case KPppCcpOptPred1:
		return _S("Predictor type1");
	case KPppCcpOptPred2:
		return _S("Predictor type2");
	case KPppCcpOptPuddle:
		return _S("Puddle");
	case KPppCcpOptHP:
		return _S("HP PPC");
	case KPppCcpOptStac:
		return _S("Stac LZS");
	case KPppCcpOptMsoft:
		return _S("Microsoft PPC");
	case KPppCcpOptGandalf:
		return _S("Gandalf");
	case KPppCcpOptV42bis:
		return _S("V42bis");
	case KPppCcpOptReserved:
		return _S("Reserved");
	case 4:
	case 5:
	case 6:
	case 7:
	case 8:
	case 9:
	case 10:
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
		return _S("unassigned");
	default:
		return _S("Unknown");
		}
	}


TInt CDummyNifLog::DumpLcp(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 code = *ptr++;
	TUint8 id = *ptr++;
	TInt len = BigEndian::Get16(ptr);
	if(len>aDes.Length())
		{
		Printf(_L("WARNING: Length reported in header was more than actual frame length\n"));
		return len;
		}
	else if (len<aDes.Length())
		Printf(_L("WARNING: Length reported in header was less than actual frame length!\n"));

	ptr += 2;
	aDes.Set(ptr, aDes.Length()-4);
	
	Printf(KCodeTextString, LcpCodeToText(code), code);
	Printf(KIdentifierLengthString, id, len);
	
	switch (code)
		{
	case KPppLcpConfigRequest:
	case KPppLcpConfigAck:
	case KPppLcpConfigNak:
	case KPppLcpConfigReject:
			{
			TInt n = len-4;
			TInt tmp = 0;
			while (n>0 && aDes.Length()>0)
				{
				tmp = DumpLcpOption(aDes);
				if (tmp == 0)	//Check for an error in the DumpLcpOption (0 is interpreted as an error)
					{
					Printf(_L("WARNING: Length reported in LCP Option was incorrect! Dumping data instead\n"));
					DumpBytes(EIGHT_SPACE_MARGIN, ptr, len-4);
					break;
					}
				n=n-tmp;
				}	

			if (n>0)
				Printf(KBytesRemainingString, n, (n>1)?"s":"");
			}

		break;
	case KPppLcpTerminateRequest:
	case KPppLcpTerminateAck:
			{
			if (len>4)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr, len-4);
			}
		break;
	case KPppLcpCodeReject:
			{
			TUint val = *ptr;
			Printf(KCodeString, val);
			}
		break;
	case KPppLcpProtocolReject:
			{
			TUint val = BigEndian::Get16(ptr);		
			Printf(KProtocolString, val);
			}
		break;
	case KPppLcpEchoRequest:
			{
			TUint val = BigEndian::Get32(ptr);	
			Printf(KNumberString, val);
			if (len>0)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr+4, len-8);
			}
		break;
	case KPppLcpEchoReply:
			{
			TUint val = BigEndian::Get32(ptr);
			Printf(KNumberString, val);
			if (len>0)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr+4, len-8);
			}
		break;
	case KPppLcpDiscardRequest:
			{
			TUint val = BigEndian::Get32(ptr);
			Printf(KNumberString, val);
			if (len>0)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr+4, len-8);
			}
		break;
	case KPppLcpIdentification:
			{
			TUint val = BigEndian::Get32(ptr);
			Printf(KNumberString, val);
			if (len>0)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr+4, len-8);
			}
		break;
	case KPppLcpTimeRemaining:
			{
			TUint val = BigEndian::Get32(ptr);
			ptr+=4;
			Printf(KNumberString, val);
			val = BigEndian::Get32(ptr);
			Printf(KSecondsString, val);
			}
		break;
	default:
		break;
		}

	return len;
	}

TInt CDummyNifLog::DumpLcpOption(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 opt = *ptr++;
	TUint8 len = *ptr++;

	if(len > aDes.Length())
		{
		Printf(_L("WARNING: Length reported in option header was more than actual frame length\n"));
		return 0;	//Return an incorrect length to flag this error.
		}

	if(len < 2)
		{
		Printf(_L("WARNING: Length reported in option header was less than a correct frame length\n"));
		return 0;	//Return an incorrect length. (the minimum correct length of an option is 2)
		}
	
	Printf(KLcpCodeString, LcpOptToText(opt), opt);
	Printf(KLengthString, len);
	
	switch (opt)
		{
	case KPppLcpOptMaxRecvUnit:
			{
			TUint val = BigEndian::Get16(ptr);
			Printf(KSizeString, val);
			}
		break;
	case KPppLcpOptEscapeCharMap:
			{
			TUint val = BigEndian::Get32(ptr);
			Printf(KMapString, val);
			}
		break;
	case KPppLcpOptAuthenticationProtocol:
			{
			TUint val = BigEndian::Get16(ptr);

			Printf(KProtocolTextString, ProtocolToText(val), val);
			if (val != KPppIdChap)
				{
				if (len>4)
					DumpBytes(EIGHT_SPACE_MARGIN, ptr+2, len-4);
				}
			else
				{
				if(len>4)
					DumpChapType(ptr+2);
				}
			}
		break;
	case KPppLcpOptQualityProtocol:
			{
			TUint val = BigEndian::Get16(ptr);
			Printf(KProtocolTextString, ProtocolToText(val), val);
			if (len>4)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr+2, len-4);
			}
		break;
	case KPppLcpOptMagicNumber:
			{
			TUint val = BigEndian::Get32(ptr);
			Printf(KNumberString, val);
			}
		break;
	case KPppLcpOptProtocolCompress:
	case KPppLcpOptAddrCtrlCompress:
		break;
	case KPppLcpOptFcsType:
			{
			TUint val = *ptr++;
			//only for display
			//Printf(KLcpOptFcsTypeString, (val&KPppDummyPPPFcs0Flag)?_S(" None"):_S(""), (val&KPppDummyPPPFcs16Flag)?_S(" 16 bit"):_S(""), (val&KPppDummyPPPFcs32Flag)?_S(" 32 bit"):_S(""));
			Printf(KLcpOptFcsTypeString, val?_S(" None"):_S(""));
			}
		break;
	case KPppLcpOptPadding:
			{
			TUint val = *ptr++;
			Printf(KMaximumBytesString, val);
			}
		break;
	case KPppLcpOptCallback:
			{
			TUint val = *ptr++;
			Printf(KCodeTextString, CallbackOpToText(val), val);
			if (len>3)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr+3, len-3);
			}
		break;
	case KPppLcpOptCompoundFrames:
		break;
		}
	aDes.Set((TUint8*)aDes.Ptr()+len, aDes.Length()-len);
	return len;
	}

TInt CDummyNifLog::DumpPap(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 code = *ptr++;
	TUint8 id = *ptr++;
	TInt len = BigEndian::Get16(ptr);
	ptr += 2;

	Printf(KCodeTextString, PapCodeToText(code), code);
	Printf(KIdentifierLengthString, id, len);
	
	if (code==1)
		{
		TInt n = *ptr++;
		TPtrC8 v;
		v.Set(ptr, n);    ptr += n;
		TBuf16<KLogBufferSize> temp;
		temp.Copy(v.Left(Min(v.Length(),KLogBufferSize)));
		Printf(KUserNameString, &temp);
		n = *ptr++;
		v.Set(ptr, n);    ptr += n;
		temp.Copy(v.Left(Min(v.Length(),KLogBufferSize)));
		Printf(KPasswordString, &temp);
		}
	else if (code==2 || code==3)
		{
		TInt n = *ptr++;
		TPtrC8 v;
		v.Set(ptr, n);    ptr += n;
		TBuf16<KLogBufferSize> temp;
		temp.Copy(v.Left(Min(v.Length(),KLogBufferSize)));
		Printf(KMessageString, &temp);
		}

	aDes.Set(aDes.Ptr()+len, aDes.Length()-len);
	return len;
	}

TInt CDummyNifLog::DumpCbcp(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 code = *ptr++;
	TUint8 id = *ptr++;
	TInt len = BigEndian::Get16(ptr);
	TInt length = len;
	ptr += 2;

	Printf(KCodeTextString, CbcpCodeToText(code), code);
	Printf(KIdentifierLengthString, id, len);

	//
	// OK we can be offered many options at once, so 
	// loop for the length and decode them.
	//
	len -= 4; // Subtract the stuff we know about

	TUint8	type;
	TUint	typeLen;
	while (len)
		{
		// Yes I know we can have a permanent loop but I just don't care
		type = *ptr++;
		switch(type)
			{
		case 1:
				{
				_LIT(string1,"        No CallBack\n");
				Write(string1);
				}
			break;
		case 2:
				{
				_LIT(string2,"        Callback to a user specified No.\n");
				Write(string2);
				}
			break;
		case 3:
				{
				_LIT(string3,"        Callback to a pre specified No.\n");
				Write(string3);
				}
			break;
		case 4:
				{
				_LIT(string4,"        Callback to one of a list of numbers\n");
				Write(string4);
				}
			break;
		default:
				{
				_LIT(string5,"        Unknown Callback type\n");
				Write(string5);
				}
			break;
		}

		if (len == 1)
			len = 0;

		typeLen = *ptr++;
			Printf(KLengthString,typeLen);

		if (typeLen > 2)
		 	Printf(KDelayString,*ptr++);

		if (typeLen > 3)
			{
			//
			// Dump the Address Type field
			//
			if (*ptr++ == 1)
				{
				_LIT(string6,"            PSTN/ISDN\n");
				Write(string6);
				}
			else
				{
				_LIT(string7,"            Other\n");
				Write(string7);
				}
			}

		//
		// Dump the NULL terminated ASCII string
		//
 		DumpBytes(EIGHT_SPACE_MARGIN, ptr, (typeLen-4));
		len -= typeLen;
		}

	aDes.Set(aDes.Ptr()+length, aDes.Length()-length);
	return length;
	}

TInt CDummyNifLog::DumpChap(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 code = *ptr++;
	TUint8 id = *ptr++;
	TInt len = BigEndian::Get16(ptr);
	ptr += 2;

	Printf(KCodeTextWithoutSpacesString,FsmCodeToText(code), code);
	Printf(KIdentifierLengthString, id, len);
	
	if (code==1 || code==2)
		{
		TInt n = *ptr++;
		DumpBytes(EIGHT_SPACE_MARGIN, ptr, n);
		ptr += n;

		n = len-(4+1+n);
		TPtrC8 v;
		v.Set(ptr, n);    ptr += n;
		TBuf16<KLogBufferSize> temp;
		temp.Copy(v);
		Printf(KNameString, &temp);
		}
	else if (code==3 || code==4)
		{
		TInt n = (len-4);
		TPtrC8 v;
		v.Set(ptr, n);
		ptr += n;
		TBuf16<KLogBufferSize> temp;
		temp.Copy(v);
		Printf(KMessageString, &temp);
		}

	aDes.Set(aDes.Ptr()+len, aDes.Length()-len);
	return len;
	}


TInt CDummyNifLog::DumpCcp(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 code = *ptr++;
	TUint8 id = *ptr++;
	TInt len = BigEndian::Get16(ptr);
	ptr += 2;
	aDes.Set(ptr, aDes.Length()-4);

	Printf(KCodeTextWithoutSpacesString,FsmCodeToText(code), code);
	Printf(KIdentifierLengthString, id, len);
	
	switch (code)
		{
	case KPppLcpConfigRequest:
	case KPppLcpConfigAck:
	case KPppLcpConfigNak:
	case KPppLcpConfigReject:
			{
			TInt n = len-4;
			TInt tmp = 0;
			while (n>0 && aDes.Length()>0)
				{
				tmp = DumpCcpOption(aDes);
				if (tmp == 0) 	//Check for an error in the DumpCcpOption (0 is interpreted as an error)
					{
					Printf(_L("WARNING: Length reported in CCP Option was incorrect! Dumping data instead\n"));
					DumpBytes(EIGHT_SPACE_MARGIN, ptr, len-4);
					break;
					}
				n=n-tmp;
				}	

			if (n>0)
				Printf(KBytesRemainingString, n, (n>1)?"s":"");
			}
		break;
	case KPppLcpTerminateRequest:
	case KPppLcpTerminateAck:
			{
			if (len>4)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr, len-4);
			}
		break;
	case KPppLcpCodeReject:
			{
			TUint val = BigEndian::Get16(ptr);
			Printf(KCodeString, val);
			}
		break;
	case KPppLcpProtocolReject:
			{
			TUint val = BigEndian::Get16(ptr);
			Printf(KProtocolString, val);
			}
		break;
		}
	return len;
	}

TInt CDummyNifLog::DumpCcpOption(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 opt = *ptr++;
	TUint8 len = *ptr++;

	if(len > aDes.Length())
		{
		Printf(_L("WARNING: Length reported in option header was more than actual frame length\n"));
		return 0;	//Return an incorrect length to flag this error.
		}

	if(len < 2)
		{
		Printf(_L("WARNING: Length reported in option header was less than a correct frame length\n"));
		return 0;	//Return an incorrect length. (the minimum correct length of an option is 2)
		}

	Printf(KCodeTextString, CcpCodeToText(opt), opt);
	Printf(KLengthString, len);

	DumpBytes(FOURTEEN_SPACE_MARGIN, ptr, len-2);
	aDes.Set((TUint8*)aDes.Ptr()+len, aDes.Length()-len);
	return len;
	}

TInt CDummyNifLog::DumpIp6cp(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 code = *ptr++;
	TUint8 id = *ptr++;
	TInt len = BigEndian::Get16(ptr);
	ptr += 2;
	aDes.Set(ptr, aDes.Length()-4);

	Printf(KCodeTextWithoutSpacesString, FsmCodeToText(code), code);
	Printf(KIdentifierLengthString, id, len);
	
	switch (code)
		{
	case KPppLcpConfigRequest:
	case KPppLcpConfigAck:
	case KPppLcpConfigNak:
	case KPppLcpConfigReject:
			{
			TInt n = len-4;
			//only for testing display
			//while (n>0 && aDes.Length()>0)
			//	n -= DumpIp6cpOption(aDes);
			if (n>0)
				Printf(KBytesRemainingString, n, (n>1)?"s":"");
			}
		break;
	case KPppLcpTerminateRequest:
	case KPppLcpTerminateAck:
			{
			if (len>4)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr, len-4);
			}
		break;
	case KPppLcpCodeReject:
			{
			TUint val = BigEndian::Get16(ptr);
			Printf(KCodeString2, val);
			}
		break;
	case KPppLcpProtocolReject:
			{
			TUint val = BigEndian::Get16(ptr);
			Printf(KProtocolString, val);
			}
		break;
		}
	return len;
	}
TInt CDummyNifLog::DumpIp(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 c = *ptr++;
//	TUint ver = c >> 4;
	TUint hlen = (c & 0xf) << 2;
//	TUint8 tos = *ptr;
	ptr++;
	TUint16 len = ByteOrder::Swap16((TUint16)(*ptr | *(ptr+1)<<8));
	ptr+=2;
	TUint16 id = ByteOrder::Swap16((TUint16)(*ptr | *(ptr+1)<<8));
	ptr+=2;
	TUint16 frag = ByteOrder::Swap16((TUint16)(*ptr | *(ptr+1)<<8));
	ptr+=2;
	TBool zf = (frag & 0x8000);
	TBool df = (frag & 0x4000);
	TBool mf = (frag & 0x2000);
	frag = (TUint16)((frag & 0x1fff)<<3);
//	TUint8 ttl = *ptr;
	ptr++;
	TUint8 proto = *ptr++;
//	TUint16 chksum = ByteOrder::Swap16((TUint16)(*ptr | *(ptr+1)<<8));
	ptr+=2;
	TUint32 srca = ByteOrder::Swap32(*ptr | (*(ptr+1)<<8) | (*(ptr+2)<<16) | (*(ptr+3)<<24));
	ptr+=4;
	TUint32 dsta = ByteOrder::Swap32(*ptr | (*(ptr+1)<<8) | (*(ptr+2)<<16) | (*(ptr+3)<<24));
	ptr+=4;
//	TBool opts = (hlen>20);

	Printf(KHdrLengthString, len, hlen);
	Printf(KSrcDstAddrString,(srca&0xff000000)>>24,(srca&0x00ff0000)>>16,(srca&0x0000ff00)>>8,(srca&0x000000ff),
							 (dsta&0xff000000)>>24,(dsta&0x00ff0000)>>16,(dsta&0x0000ff00)>>8,(dsta&0x000000ff));
	Printf(KIDFragmentString, id, frag, df?_S("<DF>"):_S(""), mf?_S("<MF>"):_S(""), zf?_S("<Z>"):_S(""));
//	Printf(KTOSTTLChksumString, tos, ttl, chksum);
	Printf(KCodeTextString, IpProtocolToText(proto), proto);
	
	if (hlen>20)
		ptr += (hlen-20);
	
	TInt n = (TInt)ptr-(TInt)aDes.Ptr();
	TInt tlen = aDes.Length()-n;
	aDes.Set(ptr, tlen);

	switch (proto)
		{
	case 1:
		return n+DumpIcmp(aDes, tlen);
	case 6:
		return n+DumpTcp(aDes, srca, dsta, tlen);
	case 17:
		return n+DumpUdp(aDes, srca, dsta, tlen);
	default:
		return n;
		}
	}

TInt CDummyNifLog::DumpIpcp(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 code = *ptr++;
	TUint8 id = *ptr++;
	TInt len = BigEndian::Get16(ptr);
	ptr += 2;
	aDes.Set(ptr, aDes.Length()-4);

	Printf(KCodeTextWithoutSpacesString, FsmCodeToText(code), code);
	Printf(KIdentifierLengthString, id, len);
	
	switch (code)
		{
	case KPppLcpConfigRequest:
	case KPppLcpConfigAck:
	case KPppLcpConfigNak:
	case KPppLcpConfigReject:
			{
			TInt n = len-4;
			TInt tmp = 0;
			while (n>0 && aDes.Length()>0)
				{
				tmp = DumpIpcpOption(aDes);
				if (tmp == 0)  	//Check for an error in the DumpIpcpOption (0 is interpreted as an error)
					{
					Printf(_L("WARNING: Length reported in IPCP Option was incorrect! Dumping data instead\n"));
					DumpBytes(EIGHT_SPACE_MARGIN, ptr, len-4);
					break;
					}
				n=n-tmp;
				}	

			if (n>0)
				Printf(KBytesRemainingString, n, (n>1)?"s":"");
			}
		break;
	case KPppLcpTerminateRequest:
	case KPppLcpTerminateAck:
			{
			if (len>4)
				DumpBytes(EIGHT_SPACE_MARGIN, ptr, len-4);
			}
		break;
	case KPppLcpCodeReject:
			{
			TUint val = BigEndian::Get16(ptr);
			Printf(KCodeString2, val);
			}
		break;
	case KPppLcpProtocolReject:
			{
			TUint val = BigEndian::Get16(ptr);
			Printf(KProtocolString, val);
			}
		break;
		}
	return len;
	}

TInt CDummyNifLog::DumpIpcpOption(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 opt = *ptr++;
	TUint8 len = *ptr++;

	if(len > aDes.Length())
		{
		Printf(_L("WARNING: Length reported in option header was more than actual frame length\n"));
		return 0;	//Return an incorrect length to flag this error.
		}

	if(len < 2)
		{
		Printf(_L("WARNING: Length reported in option header was less than a correct frame length\n"));
		return 0;	//Return an incorrect length. (the minimum correct length of an option is 2)
		}

	Printf(KCodeTextString, IpcpCodeToText(opt), opt);
	Printf(KLengthString2, len);
	
   TUint32 val;

	switch (opt)
		{
	case KPppIpcpOptIpAddresses:
		val = BigEndian::Get32(ptr);
		Printf(KRemoteAddrString,(val&0xff000000)>>24,(val&0x00ff0000)>>16,(val&0x0000ff00)>>8,(val&0x000000ff));
		val = BigEndian::Get32(ptr+4);
		Printf(KOurAddrString,(val&0xff000000)>>24,(val&0x00ff0000)>>16,(val&0x0000ff00)>>8,(val&0x000000ff));
		break;
	case KPppIpcpOptIpCompressionProtocol:
			{
			TUint prot = BigEndian::Get16(ptr);
			ptr += 2;
			Printf(KProtocolTextString, ProtocolToText(prot), prot);
			if (len>4)
				{
				switch (prot)
					{
				case KPppIdVjCompTcp:
					Printf(KMaxSlotString, *ptr++);
					Printf(KCompSlotString, *ptr++);
					break;
				default:
					DumpBytes(FOURTEEN_SPACE_MARGIN, ptr+4, len-4);
					break;
					}
				}
			}
		break;
	case KPppIpcpOptIpAddress:
	case KPppIpcpOptPrimaryDnsAddress:
	case KPppIpcpOptSecondaryDnsAddress:
	case KPppIpcpOptPrimaryNbnsAddress:
	case KPppIpcpOptSecondaryNbnsAddress:
			{
			val = BigEndian::Get32(ptr);
			Printf(KAddrString,(val&0xff000000)>>24,(val&0x00ff0000)>>16,(val&0x0000ff00)>>8,(val&0x000000ff));
			}
		break;
		}
	aDes.Set((TUint8*)aDes.Ptr()+len, aDes.Length()-len);
	return len;
	}

TInt CDummyNifLog::DumpIp6(TPtrC8& aDes)
	{
	// This dumps the main IPv6 Header, no support for option headers
	// IPv6 Headers are FIXED length, but are chainable...
	TUint16* ptr = (TUint16*)aDes.Ptr();
	
	// First 32 bits contain version(4), class(8), Flow Label(20)
	
	TUint32 first = ByteOrder::Swap32((TUint32) *ptr);
	//TUint8 ver = (TUint8)((first >> 28) & 0xf);
	TUint8 cls = (TUint8)((first >> 20) & 0xff);
	TUint32 flowLab = (first & 0xfffff);
	ptr+=2;

	// Second 32 bits contain payload length (16), next header type (8), hop limit (8)
	TUint16 payLoadLen = ByteOrder::Swap16( *ptr++ );
	TUint16 next = ByteOrder::Swap16( *ptr++ ); 
	TUint8 nextHead = (TUint8)((next >> 8) & 0xff);
	TUint8 hopLimit = (TUint8)(next & 0xff);
	
	// Source address (128 bits)
	TUint16 s1 = ByteOrder::Swap16( *ptr++ );
	TUint16 s2 = ByteOrder::Swap16( *ptr++ );
	TUint16 s3 = ByteOrder::Swap16( *ptr++ );
	TUint16 s4 = ByteOrder::Swap16( *ptr++ );
	TUint16 s5 = ByteOrder::Swap16( *ptr++ );
	TUint16 s6 = ByteOrder::Swap16( *ptr++ );
	TUint16 s7 = ByteOrder::Swap16( *ptr++ );
	TUint16 s8 = ByteOrder::Swap16( *ptr++ );
	
	// Destination address (128 bits)
	TUint16 a1 = ByteOrder::Swap16( *ptr++ );
	TUint16 a2 = ByteOrder::Swap16( *ptr++ );
	TUint16 a3 = ByteOrder::Swap16( *ptr++ );
	TUint16 a4 = ByteOrder::Swap16( *ptr++ );
	TUint16 a5 = ByteOrder::Swap16( *ptr++ );
	TUint16 a6 = ByteOrder::Swap16( *ptr++ );
	TUint16 a7 = ByteOrder::Swap16( *ptr++ );
	TUint16 a8 = ByteOrder::Swap16( *ptr++ );
	
	//Printf(_L("    Version is %d"),ver);	// Should be 6 for IPv6 !!
	Printf(KIpv6Class, cls);
	Printf(KIpv6FlowLabel, flowLab);
	Printf(KIpv6PayloadLen, payLoadLen);
	Printf(KIpv6NextHeadType, nextHead);
	Printf(KIpv6HopLimit, hopLimit);
	Printf(KIpv6SrcAddress, s1,s2,s3,s4,s5,s6,s7,s8);
	Printf(KIpv6DstAddress, a1,a2,a3,a4,a5,a6,a7,a8);
	
	TInt n = (TInt)ptr-(TInt)aDes.Ptr();
	TInt tlen = aDes.Length()-n;
	aDes.Set( (TUint8*) ptr, tlen);

	switch (nextHead)
		{
		case 6:		// TCP Packet
			Printf(_L("        TCP Data"));
			//DumpTcp(aDes);
			HexDump(EIGHT_SPACE_MARGIN,EIGHT_SPACE_MARGIN, aDes.Ptr(), tlen);
			break;
		case 17:	// UDP Packet
			Printf(_L("        UDP Data"));
			DumpUdp(aDes,s8,a8,tlen);
			break;
		case 43:	// Routing Header
			Printf(_L("        Routing Header"));
			//DumpRouter
			HexDump(EIGHT_SPACE_MARGIN,EIGHT_SPACE_MARGIN, aDes.Ptr(), tlen);
			break;
		case 44:	// Fragment Header
			Printf(_L("        Packet Fragment"));
			//DumpFragment
			HexDump(EIGHT_SPACE_MARGIN,EIGHT_SPACE_MARGIN, aDes.Ptr(), tlen);
			break;
		case 50:	// ESP Payload
			Printf(_L("        ESP Payload"));
			HexDump(EIGHT_SPACE_MARGIN,EIGHT_SPACE_MARGIN, aDes.Ptr(), tlen);
			break;
		case 58:	// ICMPv6
			Printf(_L("        ICMPv6"));
			DumpIcmp(aDes,tlen);
			break;
		case 59:	// No Next Header
			Printf(_L("        NO NEXT HEADER"));
			HexDump(EIGHT_SPACE_MARGIN,EIGHT_SPACE_MARGIN, aDes.Ptr(), tlen);
			break;
		default:
			Printf(KIpv6UnknownHeadType, nextHead);
			HexDump(EIGHT_SPACE_MARGIN,EIGHT_SPACE_MARGIN, aDes.Ptr(), tlen);
		}

	return n;	
	}

TInt CDummyNifLog::DumpVjCompTcp(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint16	change = *ptr++;
	TUint8	urgent=0;
	TInt16	window=0;
	TUint16	ack=0;
	TUint16	sequence=0;
	TBuf<50> changeMaskBuf;;
	TUint8	connection=0;

	changeMaskBuf.Append(KChangeMaskString);

	if (change & KVjCompMaskConn)
		{	
		_LIT(string7,"C");
		changeMaskBuf.Append(string7);
		connection = *ptr++;
		}

	TUint16 checksum = BigEndian::Get16(ptr);
	ptr += 2;

	if (change & KVjCompMaskPush)
		{
		_LIT(string8,"P");
		changeMaskBuf.Append(string8);
		}

	/*
	*	Don't reorder SpecialI && SpecialD, they are like this
	*	as SpecialD is the SWAU bits and SpecialI is SWU
	*
	*/

	if ((change & KVjCompMaskSpecials) == KVjCompMaskSpecialD)
		{
		_LIT(string1,"	Special D");
		Write(string1);
		}
	else if ((change & KVjCompMaskSpecials) == KVjCompMaskSpecialI)
		{
		_LIT(string2,"	Special I");
		Write(string2);
		}
	else
		{
		if (change & KVjCompMaskUrgent)
			{
			_LIT(string3,"U");
			changeMaskBuf.Append(string3);
			urgent = *ptr++;
			}

		if (change & KVjCompMaskWindow )
			{
			//only for display
			//window = (TInt16)DecodeSignedDelta(ptr);
			_LIT(string4,"W");
			changeMaskBuf.Append(string4);
			}

		if (change & KVjCompMaskAck )
			{
			//only for display
			//ack = DecodeDelta(ptr);
			_LIT(string5,"A");
			changeMaskBuf.Append(string5);
			}

		if (change & KVjCompMaskSeq)
			{	
			//only for display
			//sequence = DecodeDelta(ptr);
			_LIT(string6,"S");
			changeMaskBuf.Append(string6);
			}
		}


	TUint16	ipId=0;
	if (change & KVjCompMaskIp)
		{	
		//only for display
	    //ipId = DecodeDelta(ptr);
		_LIT(string9,"I");
		changeMaskBuf.Append(string9);
		}

	Printf(TRefByValue<const TDesC>(changeMaskBuf), change);

	Printf(KChecksumString, checksum);

	if (change & KVjCompMaskConn)
		{
		Printf(KConnectionString,connection);
		}

	if	(urgent)
		{
		_LIT(string10,"	Urgent Delta = 0x%x");
		Printf(string10,urgent);
		}

	if (window)
		{
		_LIT(string11,"	Window Delta = %d");
		Printf(string11,window);
		}

	if (ack)
		{
		_LIT(string12,"	Ack Delta = 0x%x");
		Printf(string12,ack);
		}

	if (sequence)
		{
		_LIT(string13,"	Sequence Delta = 0x%x");
		Printf(string13,sequence);
		}

	if (ipId)
		{
		_LIT(string14,"	IPId = 0x%x");
		Printf(string14,ipId);
		}

	return 1;
	}
TInt CDummyNifLog::DumpVjUncompTcp(TPtrC8& aDes)
	{

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 c = *ptr++;
//	TUint ver = c >> 4;
	TUint hlen = (c & 0xf) << 2;
//	TUint8 tos = *ptr;
	ptr++;
	TUint16 len = ByteOrder::Swap16((TUint16)(*ptr++ | *ptr++<<8));
	TUint16 id = ByteOrder::Swap16((TUint16)(*ptr++ | *ptr++<<8));
	TUint16 frag = ByteOrder::Swap16((TUint16)(*ptr++ | *ptr++<<8));
	TBool zf = (frag & 0x8000);
	TBool df = (frag & 0x4000);
	TBool mf = (frag & 0x2000);
	frag = (TUint16)((frag & 0x1fff)<<3);
//	TUint8 ttl = *ptr;
	ptr++;
	TUint8 proto = *ptr++;
//	TUint16 chksum = ByteOrder::Swap16((TUint16)(*ptr | *(ptr+1)<<8));
	ptr+=2;
	TUint32 srca = ByteOrder::Swap32(*ptr | (*(ptr+1)<<8) | (*(ptr+2)<<16) | (*(ptr+3)<<24));
	ptr+=4;
	TUint32 dsta = ByteOrder::Swap32(*ptr | (*(ptr+1)<<8) | (*(ptr+2)<<16) | (*(ptr+3)<<24));
	ptr+=4;
//	TBool opts = (hlen>20);

	Printf(KHdrLengthString, len, hlen);
	Printf(KSrcDstAddrString, (srca&0xff000000)>>24,(srca&0x00ff0000)>>16,(srca&0x0000ff00)>>8,(srca&0x000000ff),
							  (dsta&0xff000000)>>24,(dsta&0x00ff0000)>>16,(dsta&0x0000ff00)>>8,(dsta&0x000000ff));
	Printf(KIDFragmentString, id, frag, df?_S("<DF>"):_S(""), mf?_S("<MF>"):_S(""), zf?_S("<Z>"):_S(""));
//	Printf(KTOSTTLChksumString, tos, ttl, chksum);
	Printf(KConnectionNoString, proto);
	
	if (hlen>20)
		ptr += (hlen-20);
	
	TInt n = (TInt)ptr-(TInt)aDes.Ptr();
	TInt tlen = aDes.Length()-n;
	aDes.Set(ptr, tlen);
	return n+DumpTcp(aDes, srca, dsta, tlen);
	}

TInt CDummyNifLog::DumpTcp(TPtrC8& aDes, TUint32 aSrcA, TUint32 aDstA, TInt aLength)
	{
	
	TInt n = Min(aLength, aDes.Length());
	TInt len = n;
	
	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint8 osum0 = ptr[16];
	ptr[16] = 0;
	TUint8 osum1 = ptr[17];
	ptr[17] = 0;

	TUint32 sum = 0;
	sum += (aSrcA >> 16);
	sum += (aSrcA & 0xffff);
	sum += (aDstA >> 16);
	sum += (aDstA & 0xffff);
	sum += 6;
	sum += n;
	while (n>1)
		{
		sum += (ptr[0]<<8);
		sum += (ptr[1]);
		ptr += 2;
		n -= 2;
		}
	if (n>0)
		sum += (ptr[0]<<8);
	while (sum>0xffff)
		{
		sum = (sum & 0xffff) + (sum>>16);
		}
	sum = ~sum & 0xffff;
	ptr = (TUint8*)aDes.Ptr();
	ptr[16] = osum0;
	ptr[17] = osum1;
	
	TUint srcp = ByteOrder::Swap16((TUint16)(*ptr | (*(ptr+1)<<8)));
	ptr +=2;
	TUint dstp = ByteOrder::Swap16((TUint16)(*ptr | (*(ptr+1)<<8)));
	ptr +=2;
	TUint32 seqnum = ByteOrder::Swap32(*ptr | (*(ptr+1)<<8) | (*(ptr+2)<<16) | (*(ptr+3)<<24));
	ptr+=4;
	TUint32 acknum = ByteOrder::Swap32(*ptr | (*(ptr+1)<<8) | (*(ptr+2)<<16) | (*(ptr+3)<<24));
	ptr+=4;

	TUint8 c = *ptr++;
	TUint hlen = (c>>4)<<2;

	c = *ptr++;
	TUint urgf = c & 0x20;
	TUint ackf = c & 0x10;
	TUint pshf = c & 0x08;
	TUint rstf = c & 0x04;
	TUint synf = c & 0x02;
	TUint finf = c & 0x01;

	TUint window = ByteOrder::Swap16((TUint16)(*ptr | (*(ptr+1)<<8)));
	ptr+=2;
	TUint chksum = ByteOrder::Swap16((TUint16)(*ptr | (*(ptr+1)<<8)));
	ptr+=2;
	TUint urgptr = ByteOrder::Swap16((TUint16)(*ptr | (*(ptr+1)<<8)));
	ptr+=2;
	
	Printf(KTCPLengthString, len, hlen);
	Printf(KPortString, srcp, dstp);
//	Printf(KDestPortString, dstp);
//	Printf(KTCPHeaderLengthString, hlen);
	Printf(KSeqAckString, seqnum, acknum);
	Printf(KFlagsString, urgf?_S(" <URG>"):_S(""), ackf?_S(" <ACK>"):_S(""), pshf?_S(" <PSH>"):_S(""),
		                      rstf?_S(" <RST>"):_S(""), synf?_S(" <SYN>"):_S(""), finf?_S(" <FIN>"):_S(""));
	Printf(KWindowUrgentString, window, urgptr);
	if (chksum != sum)
		Printf(KChecksumString3, chksum, sum);

	if (hlen>20)
		{
		_LIT(string2,"	TCP Options %d bytes");
		Printf(string2, hlen-20);
		TInt h, i, opt, optlen=0;
		h = hlen-20;
		for (i=0; i<h; i+=optlen)
			{
			opt = ptr[i];
			if (opt == 0) // KTcpOptEol
				break;
			if (opt == 1) // KTcpOptNop
				optlen = 1;
			else
				{
				if (i+1 >= h)
					break;
				optlen = ptr[i+1];
				if (optlen < 2)
					optlen = 2;
				}

			switch (opt)
				{
			case 1:
					{
					_LIT(string3,"	    NOP");
					Write(string3);
					}
				break;
			case 2:
					{
					_LIT(string4,"	    Max Seg Size = %d");
					Printf(string4, BigEndian::Get16(ptr+i+2));
					}
				break;
			default:
					{
					_LIT(string5,"	    Unknown [0x%02x]");
					Printf(string5, opt);
					}
				break;
				}
			}
		}
	
	ptr += (hlen-20);
	TInt n1 = (TInt)aDes.Ptr()-(TInt)ptr;
	aDes.Set(ptr, aDes.Length()-n1);
	return n1;
	}

TInt CDummyNifLog::DumpIcmp(TPtrC8& aDes, TInt aLength)
	{

	if (aLength < 2)
		return 0;

	TUint8* ptr = (TUint8*)aDes.Ptr();

	_LIT(string1,"	    Type = %d, Code = %d\n");
	Printf(string1, *ptr, *(ptr+1));
	HexDump(FOURTEEN_SPACE_MARGIN, FOURTEEN_SPACE_MARGIN, ptr, aLength);
	return 0;
	}

TInt CDummyNifLog::DumpUdp(TPtrC8& aDes, TUint32 /* aSrcA */, TUint32 /*aDstA */, TInt aLength)
	{
	if (aLength < 6)
		return 0;

	TUint8* ptr = (TUint8*)aDes.Ptr();
	TUint srcp = ByteOrder::Swap16((TUint16)(*ptr | (*(ptr+1)<<8)));
	ptr +=2;
	TUint dstp = ByteOrder::Swap16((TUint16)(*ptr | (*(ptr+1)<<8)));
	ptr +=2;
	TUint16 len = ByteOrder::Swap16((TUint16)(*ptr | (*(ptr+1)<<8)));
	ptr += 2;

	ptr += 2;						// skip checksum
	Printf(KUDPLengthPortString, len, srcp, dstp);
	//Printf(KPortString, srcp, dstp);

	//for testing only
	return 0;
	}

void CDummyNifLog::Dump(RMBufChain& aPacket, TInt aChannel)
	{

	RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(aPacket);
	TUint prot = TPppAddr::Cast(info->iDstAddr).GetProtocol();
	
	TBuf8<1536> buf;
	buf.SetMax();
	aPacket.CopyOut(buf, aPacket.First()->Length());
	
	if (aChannel==KDummyPPPSendChannel)
		{
		_LIT(string1,"Dummy PPP Send %d bytes");
		Printf(string1, info->iLength);
		}
	else if (aChannel==KDummyPPPRecvChannel)
		{
		_LIT(string2,"Dummy PPP Recv %d bytes");
		Printf(string2, info->iLength);
		}
	else
		{
		_LIT(string3,"Dummy PPP %d bytes");
		Printf(string3, info->iLength);
		}

	TPtrC8 des(buf);
	switch (prot)
		{
	case KPppIdLcp:
		DumpLcp(des);
		break;
	case KPppIdPap:
		DumpPap(des);
		break;
	case KPppIdChap:
		DumpChap(des);
		break;
	case KPppIdIpcp:
		DumpIpcp(des);
		break;
	case KPppIdIp6cp:
		DumpIp6cp(des);
		break;
	case KPppIdIp:
		DumpIp(des);
		break;
	case KPppIdIp6:
		DumpIp6(des);
		break;
	case KPppIdVjCompTcp:
		DumpVjCompTcp(des);
		break;
	case KPppIdVjUncompTcp:
		DumpVjUncompTcp(des);
		break;

	default:
		Printf(_L("Raw Bytes:"));
		HexDump(NULL,_S(""),des.Ptr(), des.Length(),8);
		Write(KEndOfLine);
	}
}

void CDummyNifLog::DumpChapType(const TUint8* aPtr)
	{

	switch (*aPtr)
		{
	case 5:
			{
			_LIT(string1,"	    Algorithm=MD5\n");
			Write(string1);
			}
		break;
	case 0x80:
			{
			_LIT(string2,"	    Algorithm=Microsoft\n");
			Write(string2);
			}
		break;
	default:
			{
			_LIT(string3,"	    Algorithm=Unknown\n");
			Write(string3);
			}
		break;
		}
	}

const TText* CDummyNifLog::CallbackOpToText(TUint aValue)
	{

	// CB Codes
	switch (aValue)
		{
	case 0:
		return _S("Location preset");
	case 1:
		return _S("Dialing string");
	case 2:
		return _S("Location identifier");
	case 3:
		return _S("E.164 number");
	case 4:
		return _S("Distinguished name");
	case 5:
		return _S("E.165 number");
	case 6:
		return _S("MS CBCP");
	default:
		return _S("Unknown operation");
		}
	}

const TText* CDummyNifLog::LcpOptToText(TUint aValue)
	{

	// LCP Options
	switch (aValue)
		{
	case KPppLcpOptMaxRecvUnit:
		return _S("Max receive size");
	case KPppLcpOptEscapeCharMap:
		return _S("Escape char map");
	case KPppLcpOptAuthenticationProtocol:
		return _S("Authentication protocol");
	case KPppLcpOptQualityProtocol:
		return _S("Quality protocol");
	case KPppLcpOptMagicNumber:
		return _S("Magic number");
	case KPppLcpOptProtocolCompress:
		return _S("Protocol field compression");
	case KPppLcpOptAddrCtrlCompress:
		return _S("Addr & Ctrl field compression");
	case KPppLcpOptFcsType:
		return _S("Fcs Type");
	case KPppLcpOptPadding:
		return _S("Padding");
	case KPppLcpOptCallback:
		return _S("Callback protocol");
	case KPppLcpOptCompoundFrames:
		return _S("Compound frames");
	case KPppLcpOptMRRU:
 		return _S("MRRU");
 	case KPppLcpOptMultiLinkEndPointDescriminator:
 		return _S("Multi-link End-Point Descriminator");
	default:
		return _S("Unknown");
		}
	}

const TText* CDummyNifLog::ProtocolToText(TUint aValue)
	{

	// Protocols
	switch (aValue)
		{
	case KPppIdLcp:
		return _S("LCP");
	case KPppIdPap:
		return _S("PAP");
	case KPppIdChap:
		return _S("CHAP");
	case KPppIdMsCbcp:
		return _S("MSCBCP");
	case KPppIdIpcp:
		return _S("IPCP");
	case KPppIdIp6cp:
		return _S("IP6CP");
	case KPppIdIp:
		return _S("IP");
	case KPppIdIp6:
		return _S("IPv6");
	case KPppIdVjCompTcp:
		return _S("VJ Comp tcp");
	case KPppIdVjUncompTcp:
		return _S("VJ Uncomp tcp");
	case KPppIdCcp:
		return _S("CCP");
	case KPppIdCompressed:
		return _S("PPP Compressed");
	default:
		return _S("Unknown");
		}
	}

void CDummyNifLog::LogUserData(RMBufChain& aPacket, TInt aChannel)
//
// Stores the current total of data transferred
//
{
	TBuf8<1536> buf;
	buf.SetMax();
	aPacket.CopyOut(buf, aPacket.First()->Length());
	
	TPtrC8 des(buf);

	TUint8* ptr = (TUint8*)des.Ptr();
	ptr+=2;
	TUint16 len = ByteOrder::Swap16((TUint16)(*ptr | *(ptr+1)<<8));

	if (aChannel==KDummyPPPSendChannel)
	{
		iSentData+=len;
	}
	else
	{
		if (aChannel==KDummyPPPRecvChannel)
			iRecvdData+=len;
	}

}

void CDummyNifLog::DumpBytes(const TText* aMargin, const TUint8* aPtr, TInt aLen)
	{
	HexDump(NULL,aMargin,aPtr,aLen,8);
	}