--- /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 <e32uid.h>
+#include <networking/vj.h>
+#include "ncpip.h"
+#include "PPPLOG.H"
+#include "PPP_VER.H"
+#include <networking/pppprog.h>
+#include <networking/pppdebug.h>
+#include <commsdattypeinfov1_1.h>
+#include <comms-infras/ss_subconnprov.h>
+#include <networking/pppbase.h>
+#include <networking/pppconfig.h>
+
+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 ; i<con->Count() ; ++i)
+ CNifFactory::ControlledDelete((*con)[i]);
+ iVJCompressorCon = NULL;
+ }
+
+
+ if(iVJDeCompressorCon)
+ {
+ con = iVJDeCompressorCon;
+ for(i=0 ; i<con->Count() ; ++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<KCommsDbSvrMaxColumnNameLength> 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<TBinderConfig4>(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;
+ }