--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/linklayerprotocols/pppnif/SPPP/ncpip6.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,610 @@
+// Copyright (c) 2003-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 <e32hal.h> // UserHal::MachineInfo()
+#include <in_sock.h> // IPv6 enhanced in_sock.h: KProtocolInet6Ip
+#include <in6_if.h> // KSoIface*, KIf*
+#include "ncpip6.h" // This
+#include "ncpip.h" // for KSlashChar
+#include "PPPLOG.H"
+#include "PppProg.h"
+#include <commsdattypeinfov1_1.h>
+#include <networking/pppconfig.h>
+
+using namespace ESock;
+
+#if defined(__VC32__) && (_MSC_VER < 1300)
+ #define PMF(x) x
+#else
+ #define PMF(x) &x
+#endif
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KNif,"Ppp");
+_LIT8(KPPPBinderIP6,"IP6");
+#endif
+
+#pragma warning (disable:4355)
+CPppBinderIp6::CPppBinderIp6(CPppLcp* aLcp)
+ : MPppFsm(aLcp, EPppPhaseNetwork, KPppIdIp6cp),
+ iPppNifSubConnectionFlow(aLcp),
+ iIpRecvr(this, PMF(CPppBinderIp6::RecvIp), PMF(CPppBinderIp6::SendFlowOn), aLcp, EPppPhaseNetwork,
+ KPppIdIp6, PMF(CPppBinderIp6::Ip6FrameError), PMF(CPppBinderIp6::Ip6KillProtocol))
+{
+#if EPOC_SDK <= 0x06000000
+ __DECLARE_NAME(_S("CPppBinderIp6"));
+#endif
+ __DECLARE_FSM_NAME(_S("IP6CP"));
+ __FLOG_OPEN(KNif, KPPPBinderIP6);
+ __FLOG_2(_L8("this:%08x\tCPppBinderIp4::CPppBinderIp6(CPppLcp& %08x)"), this, &iPppNifSubConnectionFlow);
+
+}
+#pragma warning (default:4355)
+
+CPppBinderIp6* CPppBinderIp6::NewL(CPppLcp* aLcp)
+ {
+ CPppBinderIp6* pppBinderIp6 = new(ELeave) CPppBinderIp6(aLcp);
+ CleanupStack::PushL(pppBinderIp6);
+ pppBinderIp6->ConstructL();
+ CleanupStack::Pop(pppBinderIp6);
+ return pppBinderIp6;
+ }
+
+CPppBinderIp6::~CPppBinderIp6()
+{
+ Deregister();
+ iIpRecvr.Deregister();
+
+ delete iSendCallBack;
+ iSendQ.Free();
+ __FLOG_CLOSE;
+}
+
+void CPppBinderIp6::ConstructL()
+ {
+ const CIPConfig* ncpConfig = Flow()->GetNcpConfig();
+ if (NULL == ncpConfig)
+ {
+ User::Leave(KErrCorrupt);
+ }
+
+ Register();
+ iIpRecvr.Register();
+
+ TCallBack scb(SendCallBack, this);
+ iSendCallBack = new(ELeave) CAsyncCallBack(scb, KIp6cpSendPriority);
+ FsmConstructL();
+ FsmOpen();
+
+ // Create a unique interface name
+ TBuf<KCommsDbSvrMaxColumnNameLength> port(ncpConfig->GetPortName());;
+ if (port.Length() != 0)
+ {
+ port.LowerCase();
+ iIfName.Format(_L("ipcp6::%S"), &port);
+ }
+ else
+ {
+ iIfName.Format(_L("ipcp6[0x%08x]"), this);
+ }
+ }
+
+MLowerDataSender* CPppBinderIp6::BindL(MUpperDataReceiver& aUpperReceiver, MUpperControl& aControl)
+{
+ __FLOG_1(_L8("CPppBinderIp6::Bind(MUpperDataReceiver %08x"), &aUpperReceiver);
+ if(iUpperControl)
+ User::Leave(KErrInUse);
+ iUpperControl = &aControl;
+ iUpperReceiver = &aUpperReceiver;
+ return this;
+}
+
+void CPppBinderIp6::UnBind(MUpperDataReceiver& aUpperReceiver, MUpperControl& aUpperControl)
+ {
+ __FLOG(_L8("CDummyNifBinder6:\tUnbind()"));
+ (void)aUpperReceiver;
+ (void)aUpperControl;
+ ASSERT(&aUpperReceiver == iUpperReceiver);
+ ASSERT(&aUpperControl == iUpperControl);
+ iUpperReceiver = NULL;
+ iUpperControl = NULL;
+ }
+
+TBool CPppBinderIp6::MatchesUpperControl(const MUpperControl* aUpperControl) const
+ {
+ return iUpperControl == aUpperControl;
+ }
+
+TInt CPppBinderIp6::Control(TUint /*aLevel*/, TUint /*aName*/, TDes8& /*aOption*/)
+{
+ return KErrNotSupported;
+}
+
+void CPppBinderIp6::SendFlowOn()
+{
+ iLowerFlowOn = ESendAccepted;
+
+ if (!iSendQ.IsEmpty())
+ {
+ iSendCallBack->CallBack();
+ }
+
+ if (iSendQ.IsEmpty() && iUpperControl)
+ {
+ iUpperFlowOn = ESendAccepted;
+ iUpperControl->StartSending();
+ }
+}
+
+void CPppBinderIp6::Error(TInt aError)
+ {
+ iUpperControl->Error(aError);
+ }
+
+
+TInt CPppBinderIp6::SendCallBack(TAny* aCProtocol)
+{
+ ((CPppBinderIp6*)aCProtocol)->DoSend();
+ return 0;
+}
+
+void CPppBinderIp6::FsmTerminationPhaseComplete()
+{
+}
+
+void CPppBinderIp6::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();
+ }
+ }
+}
+
+MLowerDataSender::TSendResult CPppBinderIp6::Send(RMBufChain& aPacket)
+ {
+
+#if EPOC_SDK==0x06000000
+ iPppLcp->StartInactiveTimer();
+#endif
+
+ RMBufPacket packet;
+ packet.Assign(aPacket);
+ RMBufPktInfo* info = packet.Unpack();
+
+ TPppAddr addr;
+ addr.SetProtocol(KPppIdIp6);
+ info->iDstAddr = addr;
+
+ packet.Pack();
+
+ iSendQ.Append(packet);
+ iSendCallBack->CallBack();
+
+ if (!FsmIsThisLayerOpen() || !iLowerFlowOn)
+ {
+ iUpperFlowOn = ESendBlocked;
+ }
+
+ return iUpperFlowOn;
+ }
+
+//-=========================================================
+// MLowerControl methods
+//-=========================================================
+TInt CPppBinderIp6::GetName(TDes& aName)
+ {
+ __FLOG(_L8("CPppNifBinder6:\tGetName()"));
+
+ aName.Copy(iIfName);
+
+ return KErrNone;
+ }
+
+TInt CPppBinderIp6::BlockFlow(MLowerControl::TBlockOption /*aOption*/)
+ {
+ iLowerFlowOn = ESendBlocked;
+ return KErrNone;
+ }
+
+TInt CPppBinderIp6::GetConfig(TBinderConfig& aConfig)
+ {
+ TBinderConfig6* config = TBinderConfig::Cast<TBinderConfig6>(aConfig);
+
+ if(config == NULL)
+ {
+ return KErrNotSupported;
+ }
+
+ config->iFamily = KAfInet6;
+
+ config->iInfo.iFeatures = KIfIsPointToPoint | KIfCanMulticast | 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);
+
+ TEui64Addr* ifId = (TEui64Addr*)&config->iLocalId;
+
+ ifId->Init();
+ ifId->SetAddress(iLocalIfId);
+
+ ifId = (TEui64Addr*)&config->iRemoteId;
+ ifId->Init();
+ ifId->SetAddress(iRemoteIfId);
+
+ // Setup static DNS address if required
+
+ if (!iPrimaryDns.IsUnspecified())
+ {
+ config->iNameSer1.SetAddress(iPrimaryDns);
+ if (!iSecondaryDns.IsUnspecified())
+ config->iNameSer2.SetAddress(iSecondaryDns);
+ }
+ return KErrNone;
+ }
+
+// ################################################################
+
+TInt CPppBinderIp6::FsmLayerStarted()
+{
+ iPppLcp->PppOpen();
+ return KErrNone;
+}
+
+#if EPOC_SDK >= 0x06010000
+void CPppBinderIp6::FsmLayerFinished(TInt aReason)
+#else
+void CPppBinderIp6::FsmLayerFinished(TInt /*aReason*/)
+#endif
+{
+#if EPOC_SDK >= 0x06010000
+ iPppLcp->PppClose(aReason);
+#else
+ iPppLcp->PppClose();
+#endif
+ Flow()->Progress(EPppProgressLinkDown, KErrNone);
+}
+
+void CPppBinderIp6::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.
+// Flow()->FlowUp(); // Inform control path: Link is up.
+ iPppLcp->NcpUp(); // Inform control path: Link is up.
+ SendFlowOn(); // Inform data path: ready to process data.
+
+ Flow()->Progress(EPppProgressLinkUp, KErrNone);
+ Flow()->BinderLinkUp(CPppLcp::EPppIp6);
+}
+
+void CPppBinderIp6::FsmLayerDown(TInt aReason)
+{
+ LOG( iPppLcp->iLogger->Printf(_L("NCPIP6::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);
+}
+
+
+void CPppBinderIp6::FsmFillinConfigRequestL(RPppOptionList& aReqList)
+{
+ const CIPConfig* ncpConfig = Flow()->GetNcpConfig();
+
+ // See whether we are configured to request a dynamic DNS address.
+ if(!ncpConfig->GetIp6DNSAddrFromServer())
+ {
+ // Setup static DNS addresses from CommDb
+ LOG(iPppLcp->iLogger->Printf(_L("Configuring static IPv6 DNS addresses"));)
+ iPrimaryDns = ncpConfig->GetIp6NameServer1();
+ iSecondaryDns = ncpConfig->GetIp6NameServer2();
+ }
+ else
+ {
+ // Ensure that static DNS addresses are set as unspecified,
+ // so they are not used in Control(KSoIfConfig).
+ iPrimaryDns = KInet6AddrNone;
+ iSecondaryDns = KInet6AddrNone;
+ }
+
+ RPppOption opt;
+ TMachineInfoV1Buf machineInfo;
+
+ //
+ // Use the 64 bit id of MARM machines as our interface id
+ //
+ UserHal::MachineInfo(machineInfo);
+ iLocalIfId.SetAddr(machineInfo().iMachineUniqueId);
+ iLocalIfId.SetUniversalBit(0);
+
+ //
+ // In WINS environment the id is zero which is no-no
+ //
+ if (iLocalIfId.IsZero())
+ {
+#ifdef NCPIP6_STATIC_ID
+ const TUint8 constantId[8] = { 0x1c, 0xe5, 0xb8, 0x4d, 0xd6, 0xfb, 0x10, 0x63 };
+ iLocalIfId.SetAddr(constantId, sizeof (constantId));
+#else
+ iLocalIfId.SetAddrRandomNZ();
+#endif
+ }
+
+ opt.SetL (KPppIp6cpOptInterfaceIdentifier, iLocalIfId.AddrPtr(), iLocalIfId.AddrLen());
+ aReqList.Append(opt);
+}
+
+void CPppBinderIp6::FsmCheckConfigRequest(RPppOptionList& aReqList, RPppOptionList& aAckList, RPppOptionList& aNakList, RPppOptionList& aRejList)
+{
+ RPppOption opt;
+
+ while (aReqList.Remove(opt))
+ {
+ switch (opt.OptType())
+ {
+ case KPppIp6cpOptCompressionProtocol:
+ aRejList.Append(opt);
+ break;
+
+ case KPppIp6cpOptInterfaceIdentifier:
+ {
+ iRemoteIfId.SetAddr(opt.ValuePtr(), opt.ValueLength());
+
+ if (iLocalIfId.Match(iRemoteIfId) || iRemoteIfId.IsZero())
+ {
+ iRemoteIfId.SetAddrRandomNZButNot(iLocalIfId);
+ Mem::Copy(opt.ValuePtr(), iRemoteIfId.AddrPtrC(), iRemoteIfId.AddrLen());
+ aNakList.Append(opt);
+ }
+ else
+ {
+ aAckList.Append(opt);
+
+ }
+ }
+ break;
+
+ default:
+ aRejList.Append(opt);
+ break;
+ }
+ }
+}
+
+void CPppBinderIp6::FsmApplyConfigRequest(RPppOptionList& aReqList)
+{
+ TMBufPktQIter iter(aReqList);
+ RPppOption opt;
+
+ while (opt = iter++, !opt.IsEmpty())
+ {
+ switch (opt.OptType())
+ {
+ case KPppIp6cpOptCompressionProtocol:
+ break;
+
+ case KPppIp6cpOptInterfaceIdentifier:
+ iRemoteIfId.SetAddr(opt.ValuePtr(), opt.ValueLength());
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void CPppBinderIp6::FsmRecvConfigAck(RPppOptionList& aRepList)
+{
+ TMBufPktQIter iter(aRepList);
+ RPppOption opt;
+
+ while (opt = iter++, !opt.IsEmpty())
+ {
+ switch (opt.OptType())
+ {
+ case KPppIp6cpOptCompressionProtocol:
+ break;
+
+ case KPppIp6cpOptInterfaceIdentifier:
+ iLocalIfId.SetAddr(opt.ValuePtr(), opt.ValueLength());
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+void CPppBinderIp6::FsmRecvConfigNak(RPppOptionList& aRepList, RPppOptionList& aReqList)
+{
+ TMBufPktQIter iter(aRepList);
+ RPppOption opt;
+
+ while (opt = iter++, !opt.IsEmpty())
+ {
+ switch (opt.OptType())
+ {
+ case KPppIp6cpOptCompressionProtocol:
+ aReqList.ReplaceOption(opt);
+ break;
+
+ case KPppIp6cpOptInterfaceIdentifier:
+ {
+ TE64Addr iIfId(opt.ValuePtr(), opt.ValueLength());
+
+ if (iLocalIfId.Match(iIfId))
+ {
+ iLocalIfId.SetAddrRandomNZButNot(iIfId);
+ Mem::Copy(opt.ValuePtr(), iLocalIfId.AddrPtrC(), iLocalIfId.AddrLen());
+ }
+ else
+ {
+ iLocalIfId.SetAddr(iIfId);
+ }
+
+ aReqList.ReplaceOption(opt);
+ }
+
+ break;
+
+ default:
+ aReqList.ReplaceOption(opt);
+ break;
+ }
+ }
+}
+
+void CPppBinderIp6::FsmRecvConfigReject(RPppOptionList& aRepList, RPppOptionList& aReqList)
+{
+ TMBufPktQIter iter(aRepList);
+ RPppOption opt;
+
+ while (opt = iter++, !opt.IsEmpty())
+ {
+ switch (opt.OptType())
+ {
+ case KPppIp6cpOptCompressionProtocol:
+ aReqList.RemoveOption(opt);
+ break;
+
+ case KPppIp6cpOptInterfaceIdentifier:
+ FsmAbort(KErrNotReady);
+ break;
+
+ default:
+ aReqList.RemoveOption(opt);
+ break;
+ }
+ }
+}
+
+void CPppBinderIp6::KillProtocol()
+{
+ FsmAbort(KErrCouldNotConnect);
+ return;
+}
+
+TBool CPppBinderIp6::FsmRecvUnknownCode(TUint8 /*aCode*/, TUint8 /*aId*/, TInt /*aLength*/, RMBufChain& /*aPacket*/)
+{
+ return EFalse;
+}
+
+// ################################################################
+
+void CPppBinderIp6::RecvIp(RMBufChain& aPacket)
+{
+ if (iUpperReceiver)
+ iUpperReceiver->Process(aPacket);
+ else
+ aPacket.Free();
+}
+
+void CPppBinderIp6::Ip6KillProtocol()
+{
+ __FLOG_2(_L8("this:%08x\tCPppBinderIp6::Ip6KillProtocol() - disconnecting because access was denied"), this, &iPppNifSubConnectionFlow);
+
+ Flow()->FlowDown(KErrAccessDenied, MNifIfNotify::EDisconnect);
+ return;
+}
+
+void CPppBinderIp6::Ip6FrameError()
+{
+ return;
+}
+
+#if EPOC_SDK >= 0x06010000
+TInt CPppBinderIp6::Notification(TAgentToNifEventType aEvent)
+{
+ if (aEvent==EAgentToNifEventTypeModifyInitialTimer)
+ {
+ ChangeTimers(ETrue);
+ }
+ else
+ {
+ __ASSERT_DEBUG(EFalse, User::Invariant());
+ }
+ return KErrNone;
+}
+#endif