diff -r 000000000000 -r af10295192d8 linklayerprotocols/pppnif/SPPP/NCPIP.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linklayerprotocols/pppnif/SPPP/NCPIP.CPP Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,1124 @@ +// Copyright (c) 1997-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: +// + +#include +#include +#include "ncpip.h" +#include "PPPLOG.H" +#include "PPP_VER.H" +#include +#include +#include +#include +#include +#include + +using namespace ESock; + +#if defined(__VC32__) && (_MSC_VER < 1300) + #define PMF(x) x +#else + #define PMF(x) &x +#endif + +_LIT(KVjComp, "vjcomp"); +#ifdef __FLOG_ACTIVE +_LIT8(KNif,"Ppp"); +_LIT8(KPPPBinderIP4,"IP4"); +#endif + +// +// PPP for ESock +// + +#ifdef __VC32__ +// warning C4355: 'this' : used in base member initializer list +#pragma warning (disable:4355) +#endif + +CPppBinderIp4::CPppBinderIp4(CPppLcp* aLcp) + : MPppFsm(aLcp, EPppPhaseNetwork, KPppIdIpcp), + iPppNifSubConnectionFlow(aLcp), + iIpRecvr(this, PMF(CPppBinderIp4::RecvIp), PMF(CPppBinderIp4::SendFlowOn), aLcp, EPppPhaseNetwork, + KPppIdIp, PMF(CPppBinderIp4::IpFrameError), PMF(CPppBinderIp4::IpKillProtocol)), + iVjCompTcpRecvr(this, PMF(CPppBinderIp4::RecvVjCompTcp), PMF(CPppBinderIp4::SendFlowOn), aLcp, EPppPhaseNetwork, + KPppIdVjCompTcp, PMF(CPppBinderIp4::VjCompTcpFrameError), PMF(CPppBinderIp4::VjCompTcpKillProtocol)), + iVjUncompTcpRecvr(this, PMF(CPppBinderIp4::RecvVjUncompTcp), PMF(CPppBinderIp4::SendFlowOn), aLcp, EPppPhaseNetwork, + KPppIdVjUncompTcp, PMF(CPppBinderIp4::VjUncompTcpFrameError), PMF(CPppBinderIp4::VjUncompTcpKillProtocol)) + { + __DECLARE_FSM_NAME(_S("IPCP")); + __FLOG_OPEN(KNif, KPPPBinderIP4); + __FLOG_2(_L8("this:%08x\tCPppBinderIp4::CPppBinderIp4(CPppLcp& %08x)"), this, &iPppNifSubConnectionFlow); + + } +#ifdef __VC32__ +#pragma warning (default:4355) +#endif + +CPppBinderIp4* CPppBinderIp4::NewL(CPppLcp* aLcp) + { + CPppBinderIp4* pppBinderIp4 = new(ELeave) CPppBinderIp4(aLcp); + CleanupStack::PushL(pppBinderIp4); + pppBinderIp4->ConstructL(); + CleanupStack::Pop(pppBinderIp4); + return pppBinderIp4; + } + +CPppBinderIp4::~CPppBinderIp4() + { + CObjectCon* con; + TInt i; + + Deregister(); + iIpRecvr.Deregister(); + iVjCompTcpRecvr.Deregister(); + iVjUncompTcpRecvr.Deregister(); + delete iSendCallBack; + + if (iVJCompressor) + { + iVJCompressor->Close(); + iVJCompressor = NULL; + } + + if (iVJDecompressor) + { + iVJDecompressor->Close(); + iVJDecompressor = NULL; + } + + // + // Delete all the Containers + // + if(iVJCompressorCon) + { + con = iVJCompressorCon; + + for(i=0 ; iCount() ; ++i) + CNifFactory::ControlledDelete((*con)[i]); + iVJCompressorCon = NULL; + } + + + if(iVJDeCompressorCon) + { + con = iVJDeCompressorCon; + for(i=0 ; iCount() ; ++i) + CNifFactory::ControlledDelete((*con)[i]); + iVJDeCompressorCon = NULL; + } + + iSendQ.Free(); + __FLOG_CLOSE; + } + + +/** +Construct the Link Protocol Object +*/ +void CPppBinderIp4::ConstructL() + { + const CIPConfig* ncpConfig = Flow()->GetNcpConfig(); + if (NULL == ncpConfig) + { + User::Leave(KErrCorrupt); + } + + Register(); + iIpRecvr.Register(); + iVjCompTcpRecvr.Register(); + iVjUncompTcpRecvr.Register(); + + TCallBack scb(SendCallBack, this); + iSendCallBack = new(ELeave) CAsyncCallBack(scb, KIpcpSendPriority); + + iVJCompressorCon = (iPppLcp->ContainerForDlls())->CreateL(); + iVJDeCompressorCon = (iPppLcp->ContainerForDlls())->CreateL(); + + FsmConstructL(); + FsmOpen(); + + // Create a unique interface name + TBuf port(ncpConfig->GetPortName()); + + if (port.Length() != 0) + { + port.LowerCase(); + iIfName.Format(_L("ipcp::%S"), &port); + } + else + { + iIfName.Format(_L("ipcp[0x%08x]"), this); + } + } + +// from MLowerDataSender +/** +Called by the IP stack to send a packet. +The packet is first VJ compressed if compression was negotiated. + +@param aPacket MBuf chain containing packet +@param aSource ignored +@return 1 for a successful send, 0 to tell upper layer to flow off +*/ +MLowerDataSender::TSendResult CPppBinderIp4::Send(RMBufChain& aPacket) + { + RMBufPacket packet; + packet.Assign(aPacket); + + TInt Protocol; + if (iVJCompressor) + { + Protocol = iVJCompressor->VJCompressFrame(packet); + return SendProtFrame(packet, Protocol ); + } + else + { + // Send normal IP frame + return SendProtFrame(packet, KPppIdIp); + } + } + +// from MLowerControl +TInt CPppBinderIp4::GetName(TDes& aName) + { + __FLOG(_L8("CPppNifBinder4:\tGetName()")); + + aName.Copy(iIfName); + return KErrNone; + } + +TInt CPppBinderIp4::BlockFlow(MLowerControl::TBlockOption /*aOption*/) + { + iLowerFlowOn = ESendBlocked; + return KErrNone; + } + +TInt CPppBinderIp4::GetConfig(TBinderConfig& aConfig) + { + TBinderConfig4* config = TBinderConfig::Cast(aConfig); + + if(config == NULL) + { + return KErrNotSupported; + } + + config->iFamily = KAfInet; + + config->iInfo.iFeatures = KPppIpIfaceFeatures | KIfIsDialup; /* Feature flags */ + + TInt rxsz, txsz; + if (FsmIsThisLayerOpen()) + { + iPppLcp->PppLink()->GetSendRecvSize(rxsz, txsz); + config->iInfo.iMtu = txsz==0 ? KPppDefaultFrameSize : txsz; + config->iInfo.iRMtu = rxsz==0 ? KPppDefaultFrameSize : rxsz; + config->iInfo.iSpeedMetric = iPppLcp->PppLink()->SpeedMetric() / 1024; + } + else + { + config->iInfo.iMtu = KPppDefaultFrameSize; + config->iInfo.iRMtu = KPppDefaultFrameSize; + config->iInfo.iSpeedMetric = 0; + } + iPppLcp->SetMaxTransferSize(config->iInfo.iMtu); + + config->iAddress.SetAddress(iLocalAddr); /* Interface IP address. */ + config->iNetMask.SetAddress(iNetworkMask); /* IP netmask. */ + config->iBrdAddr.SetAddress(iRemoteAddr); /* IP broadcast address. */ + config->iDefGate.SetAddress(iRemoteAddr ? iRemoteAddr : iLocalAddr); /* IP default gateway or peer address (if known). */ + config->iNameSer1.SetAddress(iPrimaryDns); /* IP primary name server (if any). */ + config->iNameSer2.SetAddress(iSecondaryDns); /* IP secondary name server (if any). */ + return KErrNone; + } + +/** +Called by the TCP/IP stack to get/set PPP NIF parameters. + +@param aLevel Must be KSOLInterface +@param aName Option name +@param aOption Data for the given option +@param aSource ignored +*/ +TInt CPppBinderIp4::Control(TUint aLevel, TUint aName, TDes8& /*aOption*/) + { + __FLOG(_L8("CPppNifBinder4::\tControl()")); + + if (aLevel==KSOLInterface) + { + switch (aName) + { +#ifdef _DEBUG + // Forces PPP to renegotiate the connection + case KSoIfForceRenegotiatePPP: + { + FsmOpen(); + return KErrNone; + } +#endif + + case KSoIfHardwareAddr: + default: + break; + } + } + return KErrNotSupported; + } + +// from MUpperControl +/** +Notifies the TCP/IP stack that it may start sending data. +*/ +void CPppBinderIp4::SendFlowOn() + { + __FLOG_1(_L("IPCP Flow On iUpperFlowOn=%d"), iUpperFlowOn); + // unblock call from lower layer, therefore immediately unblock + iLowerFlowOn = ESendAccepted; + // Ensure Send queue is empty before reopening upper flow + if (!iSendQ.IsEmpty()) + iSendCallBack->CallBack(); + if (iSendQ.IsEmpty()) + { + iUpperFlowOn = ESendAccepted ; + __FLOG(_L("Start Sending to IP from Ready()")); + iUpperControl->StartSending(); + } + } + + +void CPppBinderIp4::Error(TInt aError) + { + iUpperControl->Error(aError); + } + +/** +Binds NCPIP to the TCP/IP stack. + +@param aId Pointer to network stack object (CProtocolBase*) +*/ +MLowerDataSender* CPppBinderIp4::BindL(MUpperDataReceiver& aUpperReceiver, MUpperControl& aControl) + { + __FLOG_1(_L8("CPppBinderIp4:\tBind(MUpperDataReceiver %08x)"), &aUpperReceiver); + if(iUpperControl) + User::Leave(KErrInUse); + iUpperControl = &aControl; + iUpperReceiver = &aUpperReceiver; + return this; + } + +void CPppBinderIp4::UnBind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl) + { + (void)aUpperReceiver; + (void)aUpperControl; + __FLOG(_L8("CDummyNifBinder4:\tUnbind()")); + ASSERT(&aUpperReceiver == iUpperReceiver); + ASSERT(&aUpperControl == iUpperControl); + iUpperReceiver = NULL; + iUpperControl = NULL; + } + +TBool CPppBinderIp4::MatchesUpperControl(const MUpperControl* aUpperControl) const +/** +Comparison routine used by Flow to determine which binder is being referred to +in an MFlowBinderControl::Unbind() call. + +@param aUpperControl MUpperControl object to compare against this binder + +@return ETrue if this binder is associated with aUpperControl, else EFalse. +*/ + { + return iUpperControl == aUpperControl; + } + +/** +Static function called asynchronously to send packets out the link. + +@param aCProtocol Pointer to this NCPIP object +@return 0 +*/ +TInt CPppBinderIp4::SendCallBack(TAny* aCProtocol) + { + ((CPppBinderIp4*)aCProtocol)->DoSend(); + return 0; + } + +/** +Dequeues packets and sends them out the link. +*/ +void CPppBinderIp4::DoSend() + { + if (FsmIsThisLayerOpen()) + { + RMBufPacket pkt; + while (iSendQ.Remove(pkt)) + { + RMBufPktInfo*info = pkt.Unpack(); + TPppAddr addr; + addr = info->iDstAddr; + TUint protocol = addr.GetProtocol(); + pkt.Pack(); + if (Flow()->Send(pkt, protocol) <= 0) + { + LOG( Flow()->iLogger->Printf(_L("IPCP Flow Off")); ) + iLowerFlowOn = ESendBlocked; + break; + } + } + if (iLowerFlowOn&&!iUpperFlowOn) + { + iUpperFlowOn = ESendAccepted; + LOG( Flow()->iLogger->Printf(_L("StartSending to IP from DoSend()")); ) + Flow()->StartSending(); + } + } + } + + +// +// NCP Upcalls from FSM +// + +/** +Opens the layer below +*/ +TInt CPppBinderIp4::FsmLayerStarted() + { + return iPppLcp->PppOpen(); + } + +/** +Closes the layer below +*/ +void CPppBinderIp4::FsmLayerFinished(TInt aReason) + { + iPppLcp->PppClose(aReason); + Flow()->Progress(EPppProgressLinkDown, KErrNone); + } + +/** +Signals up event to next layer above +*/ +void CPppBinderIp4::FsmLayerUp() + { + // PPP is up. Inform the stakeholders. + // Note: + // It is important to signal Link Up first, then Flow On. + // Some clients, (e.g SPUD) may make assumptions as to the order of these notifications. + // Until LinkLayer Up is received, SPUD assumes that the NIF is not ready. + // Sending Flow On before LinkLayer Up may cause these clients to make the wrong conclusions and misbehave. + + iPppLcp->NcpUp(); // Inform control path: Link is up. + SendFlowOn(); // Inform data path: ready to process data. + + if(!iPppLcp->QueryExternalIPConfiguration()) + { + // Only send the LinkUp progress if we're not + // doing Mobile IP. If we are doing MIP then + // the LinkUp progress should be generated in + // the MIP plugin module after it has finished + // its own negotiation + Flow()->Progress(EPppProgressLinkUp, KErrNone); + Flow()->BinderLinkUp(CPppLcp::EPppIp4); + } + } + +/** +Signals down event to next layer above +*/ +void CPppBinderIp4::FsmLayerDown(TInt aReason) + { + LOG( iPppLcp->iLogger->Printf(_L("CPppBinderIp4::FsmLayerDown reason[%d]."),aReason); ) + + // Mobile IP Inter-PDSN Handoff support. + if(KErrNone == aReason) + { + Flow()->FlowDown(aReason, MNifIfNotify::ENoAction); + return; + } + + // If the layer is down due to an error, it means that the FSM is terminating. + + // RFC1661 compliant Termination sequence support: + if(iTerminateRequestEnabled || iTerminateAckEnabled) + { + // LCP signals the Down event on all NCPs: + // We don't want to signal to Nifman from here, because LCP is not finished yet. + // We let LCP handle disconnection notification to Nifman + return; + } + + + // Legacy shutdown support: + // Notify SCPR. + // When legacy shutdown is no longer required, this code can be safely removed. + if(KErrCommsLineFail == aReason && FsmIsThisLayerOpen()) + { + // This is a legacy EReconnect scenario + Flow()->FlowDown(aReason, MNifIfNotify::EReconnect); + } + else + { + Flow()->FlowDown(aReason, MNifIfNotify::EDisconnect); + } + + Flow()->Progress(EPppProgressLinkDown, aReason); + } + + + +/** +Fills in Config Request to be sent +*/ +void CPppBinderIp4::FsmFillinConfigRequestL(RPppOptionList& aRequestList) + { + const CIPConfig* ncpConfig = Flow()->GetNcpConfig(); + + // See whether we are configured to request a dynamic IP address. If so, make + // sure we get one by setting iLocalAddr to 0.0.0.0 + if(!ncpConfig->GetIpAddrFromServer()) + { + LOG(iPppLcp->iLogger->Printf(_L("Requesting static IP address"));) + iLocalAddr = ncpConfig->GetIpAddress(); + } + else + { + LOG(iPppLcp->iLogger->Printf(_L("Requesting dynamic IP address"));) + iLocalAddr = KInetAddrNone; + } + + // See whether we are configured to request a dynamic DNS address. If so, make + // sure we get one by setting iPrimaryDns and iSecondaryDns to 0.0.0.0 + if(!ncpConfig->GetIp4DNSAddrFromServer()) + { // Static addresses + LOG(iPppLcp->iLogger->Printf(_L("Requesting static DNS address"));) + iPrimaryDns = ncpConfig->GetIp4NameServer1(); + iSecondaryDns = ncpConfig->GetIp4NameServer2(); + } + else + { // set to 0 for dynamic address request + LOG(iPppLcp->iLogger->Printf(_L("Requesting dynamic DNS address"));) + iPrimaryDns = KInetAddrNone; + iSecondaryDns = KInetAddrNone; + } + iPrimaryNbns = KInetAddrNone; + iSecondaryNbns = KInetAddrNone; + + iNetworkMask = ncpConfig->GetIpNetMask(); + if(iNetworkMask) + { + TUint32 mask=~1u, bits=iNetworkMask; + while((bits&1)==0) + { + bits>>=1; + mask<<=1; + } + iNetworkMask = mask; + } + + iRemoteAddr = ncpConfig->GetIpGateway(); // Field use differently in server mode (GPRS Ip gateway) + + iVJCompressionOn = ncpConfig->GetEnableIpHeaderComp(); + if (iVJCompressionOn) + { + _LIT(KVJCompDll, "vjcomp.dll"); + iVJCompressionOn = iPppLcp->DoesDllExist(KVJCompDll); + } + + if (iVJCompressionOn) + { + const TUint32 CompressionOptions = (KPppIdVjCompTcp << 16) | (KDesiredVjSlot << 8) | KVjCompSlotId; + aRequestList.CreateAndAddL(KPppIpcpOptIpCompressionProtocol, CompressionOptions); + } + + if(!iPppLcp->QueryExternalIPConfiguration()) + { + // Don't ask for IP address if we get it with another protocol. + aRequestList.CreateAndAddL(KPppIpcpOptIpAddress, iLocalAddr); + } + + if (ncpConfig->GetIp4DNSAddrFromServer()) + { + aRequestList.CreateAndAddL(KPppIpcpOptPrimaryDnsAddress, iPrimaryDns); + // aRequestList.CreateAndAddL(KPppIpcpOptPrimaryNbnsAddress, iPrimaryNbns); + aRequestList.CreateAndAddL(KPppIpcpOptSecondaryDnsAddress, iSecondaryDns); + // aRequestList.CreateAndAddL(KPppIpcpOptSecondaryNbnsAddress, iSecondaryNbns); + } + // Nbns negotiation removed to speed things up + // + } + +/** +Checks options in a received config request. +Each option is added to the appropriate Ack, Nak or Rej list. +Upcall from the FSM. + +@param aRequestList LCP options to check +@param aAckList Acked LCP options +@param aNakList Naked LCP options +@param aRejList Rejected LCP options +*/ +void CPppBinderIp4::FsmCheckConfigRequest(RPppOptionList& aRequestList, RPppOptionList& aAckList, RPppOptionList& aNakList, RPppOptionList& aRejList) + { + RPppOption opt; + while (aRequestList.Remove(opt)) + { + switch (opt.OptType()) + { + case KPppIpcpOptIpCompressionProtocol: + if (iVJCompressionOn) + { + TUint16 CompressionProtocol = 0; // Invalid compression protocol + TUint Length = opt.ValueLength(); + if (Length >= 2) + CompressionProtocol = BigEndian::Get16(opt.ValuePtr()); + + if (CompressionProtocol == KPppIdVjCompTcp) + { + // + // VJ Compression + // + TUint8* Options = opt.ValuePtr(); + Options += 2; + + if (*Options >= KMinVjSlot && *Options <= KDesiredVjSlot) + { + iMaxVJSlots = *Options++; + iCompressConnId = *Options++; + // + // If these values are OK then ACK + // + aAckList.Append(opt); + } + else + { + aNakList.Append(opt); + } + } + else + { + // Unknown compression protocol + aRejList.Append(opt); + } + } + aRejList.Append(opt); + break; + case KPppIpcpOptIpAddress: + { + const TUint32 addr = BigEndian::Get32(opt.ValuePtr()); + + if ((iPppLcp->PppLinkMode()== CPppLcpConfig::EPppLinkIsServer) + && (addr != iRemoteAddr) + && (iRemoteAddr != KInetAddrNone)) + { + // If peer doesn't know its correct IP address but we do, tell it + BigEndian::Put32(opt.ValuePtr(), iRemoteAddr); + aNakList.Append(opt); + } + else if ((addr == KInetAddrNone) && + ((iPppLcp->PppLinkMode() != CPppLcpConfig::EPppLinkIsServer) || + ((iPppLcp->PppLinkMode() == CPppLcpConfig::EPppLinkIsServer) && (iRemoteAddr == KInetAddrNone)))) + { + // If peer doesn't know its IP address and neither do we, reject the request + aRejList.Append(opt); + } + else + { + // Peer knows its own IP address and we have no reason to believe its wrong + aAckList.Append(opt); + } + break; + } + case KPppIpcpOptIpAddresses: + { + const TUint32 remoteAddr = BigEndian::Get32(opt.ValuePtr()); + const TUint32 addr = BigEndian::Get32(opt.ValuePtr()+4); + + // TODO: This negotiation isn't very robust + if (remoteAddr == KInetAddrNone) + { + if (iPppLcp->PppLinkMode()!= CPppLcpConfig::EPppLinkIsServer) + { + aRejList.Append(opt); + } + else + { + BigEndian::Put32(opt.ValuePtr(), iRemoteAddr); + aNakList.Append(opt); + } + } + else if (addr == KInetAddrNone) + { + // It doesn't matter how we found our local address; if we know it, tell the peer + if (iLocalAddr != KInetAddrNone) + { + BigEndian::Put32(opt.ValuePtr()+4, iLocalAddr); + } + aNakList.Append(opt); + } + else + { + aAckList.Append(opt); + } + break; + } + case KPppIpcpOptPrimaryDnsAddress: + { + const TUint32 reqDns = BigEndian::Get32(opt.ValuePtr()); + if (reqDns != KInetAddrNone) + { + // Accept whatever DNS address the remote wants + aAckList.Append(opt); + } + else + { + if ((iPppLcp->PppLinkMode()== CPppLcpConfig::EPppLinkIsServer) && (iPrimaryDns != KInetAddrNone)) + { + // Give it our DNS address if we have one for it + BigEndian::Put32(opt.ValuePtr(), iPrimaryDns); + aNakList.Append(opt); + } + else + { + // We don't have any DNS addresses to give the peer + aRejList.Append(opt); + } + } + break; + } + case KPppIpcpOptSecondaryDnsAddress: + { + const TUint32 reqDns = BigEndian::Get32(opt.ValuePtr()); + if (reqDns != KInetAddrNone) + { + // Accept whatever DNS address the remote wants + aAckList.Append(opt); + } + else + { + if ((iPppLcp->PppLinkMode()== CPppLcpConfig::EPppLinkIsServer) && (iSecondaryDns != KInetAddrNone)) + { + // Give it our DNS address if we have one for it + BigEndian::Put32(opt.ValuePtr(), iSecondaryDns); + aNakList.Append(opt); + } + else + { + // We don't have any DNS addresses to give the peer + aRejList.Append(opt); + } + } + break; + } + default: + aRejList.Append(opt); + break; + } + } + } + +/** +Loads the VJ compressor DLL and creates a compressor object. + +@return VJ compressor object +*/ +CVJCompressorIf* CPppBinderIp4::LoadVJCompressorL() + { + CVJCompFactory* Factory=NULL; + CVJCompressorIf* VJCompressor; + + Factory = (CVJCompFactory*)FindPppFactoryL(KVjComp, TUid::Uid(KSharedLibraryUidValue), *iVJCompressorCon); + + CleanupStack::PushL(TCleanupItem(CNifFactory::Cleanup, Factory)); + VJCompressor = Factory->NewVJCompressorL(iMaxVJSlots, iCompressConnId); + CleanupStack::PopAndDestroy(); // Close extra reference on Factory + + return VJCompressor; + } + +/** +Loads the VJ decompressor DLL and creates a decompressor object. + +@return VJ decompressor object +*/ +CVJDeCompressorIf* CPppBinderIp4::LoadVJDeCompressorL() + { + CVJCompFactory* Factory=NULL; + CVJDeCompressorIf* VJDeCompressor; + + Factory = (CVJCompFactory*)FindPppFactoryL(KVjComp, TUid::Uid(KSharedLibraryUidValue), *iVJDeCompressorCon); + CleanupStack::PushL(TCleanupItem(CNifFactory::Cleanup, Factory)); + VJDeCompressor = Factory->NewVJDeCompressorL(iMaxVJSlots); + CleanupStack::PopAndDestroy(); // Close extra reference on Factory + + return VJDeCompressor; + } + + +/** +Applies options in a received config request (that was ACK'd). +Upcall from the FSM. + +@param aRequestList NCPIP options to use +*/ +void CPppBinderIp4::FsmApplyConfigRequest(RPppOptionList& aRequestList) + { + TMBufPktQIter iter(aRequestList); + RPppOption opt; + while (opt = iter++, !opt.IsEmpty()) + { + switch (opt.OptType()) + { + case KPppIpcpOptIpCompressionProtocol: + // + // Load the VJ DLL + // + if (iVJCompressor != NULL) + { + iVJCompressor->Close(); + iVJCompressor = NULL; + } + + TRAPD( Ret, iVJCompressor = LoadVJCompressorL();) + if (Ret != KErrNone) + { + // + // Couldn't load the DLL for some reason!!! + // We're in trouble now, the only reason I can + // forsee is Out of memory PRR 18/3/98 + // + FsmAbort(Ret); + } + break; + case KPppIpcpOptIpAddress: + iRemoteAddr = BigEndian::Get32(opt.ValuePtr()); + if (iRemoteAddr == KInetAddrNone) + FsmAbort(KErrNotReady); + break; + case KPppIpcpOptIpAddresses: + iRemoteAddr = BigEndian::Get32(opt.ValuePtr()); + if (iRemoteAddr == KInetAddrNone) + FsmAbort(KErrNotReady); + iLocalAddr = BigEndian::Get32(opt.ValuePtr()+4); + if (iLocalAddr == KInetAddrNone) + FsmAbort(KErrNotReady); + break; +// case KPppIpcpOptPrimaryDnsAddress: +// iPrimaryDns = BigEndian::Get32(opt.ValuePtr()); +// break; +// case KPppIpcpOptSecondaryDnsAddress: +// iSecondaryDns = BigEndian::Get32(opt.ValuePtr()); +// break; + default: + break; + } + } + } + +/** +Applies the options received in a Config Ack +Upcall from the FSM. + +@param aReplyList NCPIP options to use +*/ +void CPppBinderIp4::FsmRecvConfigAck(RPppOptionList& aReplyList) + { + TMBufPktQIter iter(aReplyList); + RPppOption opt; + while (opt = iter++, !opt.IsEmpty()) + { + switch (opt.OptType()) + { + case KPppIpcpOptIpCompressionProtocol: + if (iVJDecompressor != NULL) + { + iVJDecompressor->Close(); + iVJDecompressor = NULL; + } + + TRAPD(ret, iVJDecompressor = LoadVJDeCompressorL();) + if (ret != KErrNone) + { + // + // Couldn't load the DLL for some reason!!! + // + iPppLcp->Stop(ret, MNifIfNotify::EDisconnect); + } + break; + case KPppIpcpOptIpAddress: + iLocalAddr = BigEndian::Get32(opt.ValuePtr()); + if (iLocalAddr == KInetAddrNone) + FsmAbort(KErrNotReady); + break; + case KPppIpcpOptPrimaryDnsAddress: + if(BigEndian::Get32(opt.ValuePtr())) + iPrimaryDns = BigEndian::Get32(opt.ValuePtr()); + break; + case KPppIpcpOptSecondaryDnsAddress: + if(BigEndian::Get32(opt.ValuePtr())) + iSecondaryDns = BigEndian::Get32(opt.ValuePtr()); + break; + case KPppIpcpOptPrimaryNbnsAddress: + if(BigEndian::Get32(opt.ValuePtr())) + iPrimaryNbns = BigEndian::Get32(opt.ValuePtr()); + break; + case KPppIpcpOptSecondaryNbnsAddress: + if(BigEndian::Get32(opt.ValuePtr())) + iSecondaryNbns = BigEndian::Get32(opt.ValuePtr()); + break; + default: + break; + } + } + } + +/** +Modifies request after receiving a Config Nak +Upcall from the FSM. + +@param aReplyList NAK'd NCPIP options +@param aReqList The associated original request to be modified +*/ +void CPppBinderIp4::FsmRecvConfigNak(RPppOptionList& aReplyList, RPppOptionList& aReqList) + { + TMBufPktQIter iter(aReplyList); + RPppOption opt; + while (opt = iter++, !opt.IsEmpty()) + { + switch (opt.OptType()) + { + case KPppIpcpOptIpCompressionProtocol: + aReqList.ReplaceOption(opt); + break; + case KPppIpcpOptIpAddress: + aReqList.ReplaceOption(opt); + break; + case KPppIpcpOptPrimaryDnsAddress: + aReqList.ReplaceOption(opt); + break; + case KPppIpcpOptSecondaryDnsAddress: + aReqList.ReplaceOption(opt); + break; + default: + aReqList.ReplaceOption(opt); + break; + } + } + } + +/** +Modifies request after receiving a Config Reject +Upcall from the FSM. + +@param aReplyList NAK'd NCPIP options +@param aReqList The associated original request to be modified +*/ +void CPppBinderIp4::FsmRecvConfigReject(RPppOptionList& aReplyList, RPppOptionList& aReqList) + { + TMBufPktQIter iter(aReplyList); + RPppOption opt; + while (opt = iter++, !opt.IsEmpty()) + { + switch (opt.OptType()) + { + case KPppIpcpOptIpCompressionProtocol: + aReqList.RemoveOption(opt); + break; + case KPppIpcpOptIpAddress: + aReqList.RemoveOption(opt); + FsmAbort(KErrNotReady); + break; + case KPppIpcpOptPrimaryDnsAddress: + aReqList.RemoveOption(opt); + break; + case KPppIpcpOptSecondaryDnsAddress: + aReqList.RemoveOption(opt); + break; + default: + aReqList.RemoveOption(opt); + break; + } + } + } + +void CPppBinderIp4::KillProtocol() + { + // This call would cause all NCPs to fail to connect + // iPppLcp->Stop(KErrCouldNotConnect,MNifIfNotify::EDisconnect); + + // This shuts down only this NCP + FsmAbort(KErrCouldNotConnect); + } + +/** +Received an unrecognised opcode - has a default implementation +*/ +TBool CPppBinderIp4::FsmRecvUnknownCode(TUint8 /*aCode*/, TUint8 /*aId*/, TInt /*aLength*/, RMBufChain& /*aPacket*/) + { + return EFalse; + } + +// + + +/** +Receives an IP packet from the lower layer. + +@param aPacket MBuf chain containing packet +*/ +void CPppBinderIp4::RecvIp(RMBufChain& aPacket) + { + if (iUpperReceiver) + iUpperReceiver->Process(aPacket); + else + aPacket.Free(); + } + + +// +// All three of these are grouped together because of the way +// this was intially designed. +// Kill Protocol is called because the protocol was rejected +// in the case of NCPIP I can't see this happening, but if it does +// we need to kill off PPP +// +void CPppBinderIp4::IpKillProtocol() + { + __FLOG_2(_L8("this:%08x\tCPppBinderIp4::IpKillProtocol() - disconnecting because access was denied"), this, &iPppNifSubConnectionFlow); + + Flow()->FlowDown(KErrAccessDenied, MNifIfNotify::EDisconnect); + return; + } + +void CPppBinderIp4::VjCompTcpKillProtocol() + { + return; + } + +void CPppBinderIp4::VjUncompTcpKillProtocol() + { + return; + } + + +void CPppBinderIp4::IpFrameError() + { + return; + } + +void CPppBinderIp4::VjCompTcpFrameError() + { + if (iVJDecompressor) + { + LOG(iPppLcp->iLogger->Printf(_L("CRC CRC CRC \n\n\n\n"));) + iVJDecompressor->CRCError(); + } + return; + } + +void CPppBinderIp4::VjUncompTcpFrameError() + { + return; + } + +/** +Receives a VJ-compressed IP packet from the lower layer. + +@param aPacket MBuf chain containing packet +*/ +void CPppBinderIp4::RecvVjCompTcp(RMBufChain& aPacket) + { + if (iVJDecompressor) + { + if (!iVJDecompressor->DecompVJComp(aPacket)) + { + aPacket.Free(); + } + else + { + RecvIp(aPacket); + } + } + else + { + aPacket.Free(); + } + return; + } + +/** +Receives a VJ-uncompressed IP packet from the lower layer. + +@param aPacket MBuf chain containing packet +*/ +void CPppBinderIp4::RecvVjUncompTcp(RMBufChain& aPacket) + { + if (iVJDecompressor) + { + if (!iVJDecompressor->DecompVJUncomp(aPacket)) + { + aPacket.Free(); + } + else + { + RecvIp(aPacket); + } + } + else + { + aPacket.Free(); + } + } + +void CPppBinderIp4::FsmTerminationPhaseComplete() + { + } + +/** +Queues a packet as-is onto the send queue and sends it out the link +via an asynchronous callback function. + +@param aPacket MBuf chain containing packet +@param aProtocol PPP protocol number +@return 1 for a successful send, 0 to tell upper layer to flow off +*/ +MLowerDataSender::TSendResult CPppBinderIp4::SendProtFrame(RMBufChain& aPacket, TUint aProtocol) + { + + RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(aPacket); + + TPppAddr addr; + addr.SetProtocol(aProtocol); + info->iDstAddr = addr; + + iSendQ.Append(aPacket); + iSendCallBack->CallBack(); + + if (!FsmIsThisLayerOpen() || !iLowerFlowOn) + { + iUpperFlowOn = ESendBlocked; + } + + return iUpperFlowOn; + } + +TInt CPppBinderIp4::Notification(TAgentToNifEventType aEvent) + { + __ASSERT_DEBUG(aEvent==EAgentToNifEventTypeModifyInitialTimer, PppPanic(EPppPanic_IncorrectNcpNotif)); + if(aEvent==EAgentToNifEventTypeModifyInitialTimer) + { + ChangeTimers(ETrue); + } + return KErrNone; + }