--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlannwif/src/Wlanbase.cpp Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,1484 @@
+/*
+* 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: Implements functions for LAN interface
+*
+*/
+
+/*
+* %version: 24 %
+*/
+
+#include <f32file.h>
+#include <e32std.h> // for TTime
+#include <nifvar.h>
+#include <nifutl.h>
+#include <es_mbuf.h>
+#include <nifmbuf.h>
+#include <comms-infras/nifprvar.h>
+#include <comms-infras/connectionsettings.h> // for KSlashChar
+#include <commdb.h>
+#include "WlanProto.h"
+#include "carddrv.h"
+#include <in_sock.h> // Header is retained, but in_sock.h is modified for ipv6
+#include "CLanIp4Bearer.h"
+#include "CLanIp6Bearer.h"
+#include <cdbcols.h>
+#include <cdblen.h>
+#include "CLanxBearer.h"
+#include "WlanProvision.h"
+#include <comms-infras/ss_metaconnprov.h> // for SAccessPointConfig
+#include <comms-infras/linkmessages.h>
+#include <elements/nm_messages_base.h>
+#include <elements/nm_messages_child.h>
+
+// From old wlan implementation
+#include <ip4_hdr.h>
+#include <ip6_hdr.h>
+#include <centralrepository.h>
+#include "am_debug.h"
+#include "EtherCardApi.h"
+#include "wlandevicesettingsinternalcrkeys.h"
+#include "NifWLMServerIf.h"
+
+
+using namespace ESock;
+using namespace Messages;
+
+_LIT8(KDescIp, "ip");
+_LIT8(KDescIcmp, "icmp");
+_LIT8(KDescIp6, "ip6");
+
+const TInt KLanxBearerPtrArrayGranularity = 2;
+const TInt KContinueSending = 1;
+const TInt KMaxDSCPValues = 64;
+
+/**
+ * Mapping of user priority values to the corresponding access classes.
+ */
+const TWlmAccessClass KUPtoAC[E8021DUserPriorityMax] =
+ {
+ EWlmAccessClassBestEffort, // E8021DUserPriorityBE
+ EWlmAccessClassBackground, // E8021DUserPriorityBK1
+ EWlmAccessClassBackground, // E8021DUserPriorityBK2
+ EWlmAccessClassBestEffort, // E8021DUserPriorityEE
+ EWlmAccessClassVideo, // E8021DUserPriorityCL
+ EWlmAccessClassVideo, // E8021DUserPriorityVI
+ EWlmAccessClassVoice, // E8021DUserPriorityVO
+ EWlmAccessClassVoice, // E8021DUserPriorityNC
+ };
+
+/**
+ * Mapping of access class transitions on packet downgrade.
+ */
+const TWlmAccessClass KNextAC[EWlmAccessClassMax] =
+ {
+ EWlmAccessClassBackground, // EWlmAccessClassBestEffort -> EWlmAccessClassBackground
+ EWlmAccessClassMax, // EWlmAccessClassBackground -> EWlmAccessClassMax
+ EWlmAccessClassBestEffort, // EWlmAccessClassVideo -> EWlmAccessClassBestEffort
+ EWlmAccessClassVideo // EWlmAccessClassVoice -> EWlmAccessClassVideo
+ };
+
+/**
+ * Mapping of IP TOS (DSCP) bits to the corresponding user priority values.
+ */
+const T8021DPriority KDSCPtoUP[KMaxDSCPValues] =
+ {
+ /* DSCP bits as binary format, DSCP byte in IPv4 packet as HEX */
+
+ /* 000000, 0x00 */E8021DUserPriorityBE, /* 000001, 0x04 */E8021DUserPriorityBE,
+ /* 000010, 0x08 */E8021DUserPriorityBE, /* 000011, 0x0C */E8021DUserPriorityBE,
+ /* 000100, 0x10 */E8021DUserPriorityBE, /* 000101, 0x14 */E8021DUserPriorityBE,
+ /* 000110, 0x18 */E8021DUserPriorityBE, /* 000111, 0x1C */E8021DUserPriorityBE,
+ /* 001000, 0x20 */E8021DUserPriorityBK1, /* 001001, 0x24 */E8021DUserPriorityBK1,
+ /* 001010, 0x28 */E8021DUserPriorityEE, /* 001011, 0x2C */E8021DUserPriorityEE,
+ /* 001100, 0x30 */E8021DUserPriorityEE, /* 001101, 0x34 */E8021DUserPriorityEE,
+ /* 001110, 0x38 */E8021DUserPriorityEE, /* 001111, 0x3C */E8021DUserPriorityEE,
+
+ /* 010000, 0x40 */E8021DUserPriorityEE, /* 010001, 0x44 */E8021DUserPriorityEE,
+ /* 010010, 0x48 */E8021DUserPriorityEE, /* 010011, 0x4C */E8021DUserPriorityEE,
+ /* 010100, 0x50 */E8021DUserPriorityEE, /* 010101, 0x54 */E8021DUserPriorityEE,
+ /* 010110, 0x58 */E8021DUserPriorityEE, /* 010111, 0x5C */E8021DUserPriorityEE,
+ /* 011000, 0x60 */E8021DUserPriorityVI, /* 011001, 0x64 */E8021DUserPriorityVI,
+ /* 011010, 0x68 */E8021DUserPriorityVI, /* 011011, 0x6C */E8021DUserPriorityVI,
+ /* 011100, 0x70 */E8021DUserPriorityVI, /* 011101, 0x74 */E8021DUserPriorityVI,
+ /* 011110, 0x78 */E8021DUserPriorityVI, /* 011111, 0x7C */E8021DUserPriorityVI,
+
+ /* 100000, 0x80 */E8021DUserPriorityVI, /* 100001, 0x84 */E8021DUserPriorityVI,
+ /* 100010, 0x88 */E8021DUserPriorityVI, /* 100011, 0x8C */E8021DUserPriorityVI,
+ /* 100100, 0x90 */E8021DUserPriorityVI, /* 100101, 0x94 */E8021DUserPriorityVI,
+ /* 100110, 0x98 */E8021DUserPriorityVI, /* 100111, 0x9C */E8021DUserPriorityVI,
+ /* 101000, 0xA0 */E8021DUserPriorityCL, /* 101001, 0xA4 */E8021DUserPriorityCL,
+ /* 101010, 0xA8 */E8021DUserPriorityCL, /* 101011, 0xAC */E8021DUserPriorityCL,
+ /* 101100, 0xB0 */E8021DUserPriorityCL, /* 101101, 0xB4 */E8021DUserPriorityCL,
+ /* 101110, 0xB8 */E8021DUserPriorityVO, /* 101111, 0xBC */E8021DUserPriorityVO,
+
+ /* 110000, 0xC0 */E8021DUserPriorityNC, /* 110001, 0xC4 */E8021DUserPriorityNC,
+ /* 110010, 0xC8 */E8021DUserPriorityNC, /* 110011, 0xCC */E8021DUserPriorityNC,
+ /* 110100, 0xD0 */E8021DUserPriorityNC, /* 110101, 0xD4 */E8021DUserPriorityNC,
+ /* 110110, 0xD8 */E8021DUserPriorityNC, /* 110111, 0xDC */E8021DUserPriorityNC,
+ /* 111000, 0xE0 */E8021DUserPriorityNC, /* 111001, 0xE4 */E8021DUserPriorityNC,
+ /* 111010, 0xE8 */E8021DUserPriorityNC, /* 111011, 0xEC */E8021DUserPriorityNC,
+ /* 111100, 0xF0 */E8021DUserPriorityNC, /* 111101, 0xF4 */E8021DUserPriorityNC,
+ /* 111110, 0xF8 */E8021DUserPriorityNC, /* 111111, 0xFC */E8021DUserPriorityNC
+ };
+
+/**
+ * Inactivity timeouts per access class.
+ */
+const TUint KTsInactivityTime[EWlmAccessClassMax] =
+ {
+ 600000000, // 600 seconds for EWlmAccessClassBestEffort
+ 600000000, // 600 seconds for EWlmAccessClassBackground
+ 120000000, // 120 seconds for EWlmAccessClassVideo
+ 30000000, // 30 seconds for EWlmAccessClassVoice
+ };
+
+EXPORT_C CLANLinkCommon::CLANLinkCommon(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf)
+ : CSubConnectionFlowBase(aFactory, aSubConnId, aProtocolIntf), iMMState(EStopped)
+ {
+ DEBUG("CLANLinkCommon::CLANLinkCommon()");
+ LOG_NODE_CREATE(KWlanLog, CLANLinkCommon);
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::LoadPacketDriverL
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::LoadPacketDriverL()
+ {
+ DEBUG("CLANLinkCommon::LoadPacketDriverL() - Creates only new class instance");
+
+ iPktDrv = CPcCardPktDrv::NewL( this );
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::NewL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CLANLinkCommon* CLANLinkCommon::NewL(CSubConnectionFlowFactoryBase& aFactory, const TNodeId& aSubConnId, CProtocolIntfBase* aProtocolIntf)
+ {
+ DEBUG("CLANLinkCommon::NewL()");
+
+ CLANLinkCommon* s=new (ELeave) CLANLinkCommon(aFactory, aSubConnId, aProtocolIntf);
+ CleanupStack::PushL(s);
+ s->ConstructL();
+ CleanupStack::Pop(s);
+ return s;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::ReadMACSettings
+// -----------------------------------------------------------------------------
+//
+TBool CLANLinkCommon::ReadMACSettings()
+ {
+ DEBUG("CLANLinkCommon::ReadMACSettings()");
+
+ TBuf8<KMACByteLength> drvMacAddr;
+ TUint8* config=iPktDrv->GetInterfaceAddress();
+ drvMacAddr.Append(&config[0],KMACByteLength); // First 3 bytes of config not part of address
+ iMacAddr.Copy(drvMacAddr); // update Ethints copy of the MAC address
+ TUint bearerLim = iBearers->Count();
+ for(TUint index=0;index<bearerLim;index++)
+ {
+ CLanxBearer* bearer=(*iBearers)[index];
+ bearer->UpdateMACAddr();
+ }
+
+ // check that the macaddress has been passed and is not 0;
+ return CheckMac(iMacAddr); // wrong.
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::Mtu
+// -----------------------------------------------------------------------------
+//
+TUint CLANLinkCommon::Mtu() const
+ {
+ DEBUG("CLanLinkCommon::Mtu()");
+
+ TInt err = KErrNone;
+ CRepository* repository = NULL;
+ TRAP( err, repository = CRepository::NewL( KCRUidWlanDeviceSettingsRegistryId ) );
+ if( err != KErrNone )
+ {
+ DEBUG1( "Could not access repository (%d), using default value for mtu(1500)", err );
+ return KEtherMaxDataLen;
+ }
+ // No need to use CleanupStack because no possibility to leave
+
+ TInt temp = 0;
+ err = repository->Get( KWlanMTU, temp );
+ if( err == KErrNone )
+ {
+ delete repository;
+ DEBUG1("MTU value from cenrep is:%d", temp);
+ if( temp > KEtherMaxDataLen || temp <= 0 )
+ {
+ DEBUG("MTU from cenrep is out of range 1-1500, setting it to 1500");
+ temp = KEtherMaxDataLen;
+ }
+ return temp;
+ }
+ else
+ {
+ DEBUG1( "Could not access repository (%d), using default value for mtu(1500)", err );
+ delete repository;
+ return KEtherMaxDataLen;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::ConstructL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CLANLinkCommon::ConstructL()
+ {
+ DEBUG("CLANLinkCommon::ConstructL()");
+
+ // Initialise class members that do not need to be read from the database
+ iBearers = new (ELeave) CLanxBearerPtrArray(KLanxBearerPtrArrayGranularity);
+ iEtherType = EStandardEthernet;
+
+ iOnlyThisBearer = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::~CLANLinkCommon
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CLANLinkCommon::~CLANLinkCommon()
+ {
+ DEBUG("CLANLinkCommon::~CLANLinkCommon()");
+
+ delete iPktDrv;
+ ASSERT(0 == iBearers->Count());
+ delete iBearers;
+ delete iPeriodic;
+ delete iWLMServerCommon;
+ for( TUint idx( 0 ); idx < EWlmAccessClassMax; ++idx )
+ {
+ delete iAcArray[idx];
+ }
+
+ LOG_NODE_DESTROY(KWlanLog, CLANLinkCommon);
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::CheckMac
+// -----------------------------------------------------------------------------
+//
+TBool CLANLinkCommon::CheckMac(TDes8& aMacAddr)
+ {
+ DEBUG("CLANLinkCommon::CheckMac()");
+
+ TUint MacBytes = 6;
+ for (TUint i=0;i<MacBytes;i++)
+ {
+ if (aMacAddr[i] != 0)
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::AcTrafficModeChanged
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::AcTrafficModeChanged(
+ TWlmAccessClass aAccessClass,
+ TWlmAcTrafficMode aMode )
+ {
+ DEBUG( "CLANLinkCommon::AcTrafficModeChanged()" );
+
+ iAcArray[aAccessClass]->SetTrafficMode( aMode );
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::AcTrafficModeChanged
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::AcTrafficStatusChanged(
+ TWlmAccessClass aAccessClass,
+ TWlmAcTrafficStatus aStatus )
+ {
+ DEBUG( "CLANLinkCommon::AcTrafficStatusChanged()" );
+
+ iAcArray[aAccessClass]->SetTrafficStatus( aStatus );
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::LinkLayerUp
+// -----------------------------------------------------------------------------
+//
+/**
+Link Layer Up
+Called by the packet driver when it is happy
+*/
+EXPORT_C void CLANLinkCommon::LinkLayerUp()
+ {
+ DEBUG("CLANLinkCommon::LinkLayerUp()");
+
+ //some drivers have a valid MAC only after negotiation finishes
+ iValidMacAddr = ReadMACSettings();
+ PostDataClientStartedMessage();
+
+ /**
+ * With the new comms framework, this KLinkLayerOpen always sent and then will be caught and swallowed
+ * at the ipproto layer if a netcfgext is being used.
+ */
+
+ /**
+ * We are forced to signal link layer open from here even though there may not
+ * be a configured IP address. This is a dirty fix because of politics...
+ */
+ PostProgressMessage(KLinkLayerOpen, KErrNone);
+
+ TUint bearerLim = iBearers->Count();
+ for(TUint index=0;index<bearerLim;index++)
+ {
+ CLanxBearer *bearer=(*iBearers)[index];
+ bearer->StartSending((CProtocolBase*)this);
+ }
+
+ // Get current traffic status for access classes.
+ TWlmAcTrafficStatusArray acArray;
+ TInt ret = iWLMServerCommon->GetAcTrafficStatus( acArray );
+ if( ret != KErrNone )
+ {
+ DEBUG1( "CLANLinkCommon::LinkLayerUp() - RWLMServer::GetAcTrafficStatus() failed with %d",
+ ret );
+
+ // Assume all access classes are admitted.
+ for( TUint idx( 0 ); idx < EWlmAccessClassMax; ++idx )
+ {
+ iAcArray[idx]->SetTrafficStatus( EWlmAcTrafficStatusAdmitted );
+ }
+ }
+ else
+ {
+ // Update access class instances with the current status.
+ for( TUint idx( 0 ); idx < EWlmAccessClassMax; ++idx )
+ {
+ iAcArray[idx]->SetTrafficStatus( acArray[idx] );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::LinkLayerDown
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CLANLinkCommon::LinkLayerDown(TInt aError, TAction aAction)
+/**
+Link Layer Down
+Called by the packet driver when the link has gone down
+
+@param aError error code
+@param aAction whether a reconnect is required or not
+*/
+ {
+ DEBUG("CLANLinkCommon::LinkLayerDown()");
+
+ // If a stop was requested from the SCpr then this LinkLayerDown()
+ // was expected. This also means the SCpr has already been sent a
+ // TDataClientStopped and the packet driver has been stopped.
+ // If on the other hand the stop was not requested a TDataClientGoneDown
+ // message needs to be sent to the SCpr and the packet driver still
+ // needs a StopInterface call - usually this would mean that aAction
+ // is EReconnect
+ if (iStopRequested == EFalse && iMMState == EStarted)
+ {
+ PostProgressMessage(KLinkLayerClosed, aError);
+ PostFlowGoingDownMessage(aError, (aAction == EReconnect) ? MNifIfNotify::EReconnect : MNifIfNotify::EDisconnect);
+ iPktDrv->StopInterface();
+ MaybePostDataClientIdle();
+ iMMState = EStopped;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::StopCb
+// -----------------------------------------------------------------------------
+//
+TInt CLANLinkCommon::StopCb(TAny* aThisPtr)
+ {
+ DEBUG("CLANLinkCommon::StopCb()");
+
+ CLANLinkCommon* self = static_cast<CLANLinkCommon*>(aThisPtr);
+ self->StopInterface();
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::StopInterface
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::StopInterface()
+ {
+ DEBUG("CLANLinkCommon::StopInterface()");
+
+ if(iPeriodic)
+ {
+ iPeriodic->Cancel();
+ delete iPeriodic;
+ iPeriodic = NULL;
+ }
+
+ iPktDrv->StopInterface();
+ PostProgressMessage(KLinkLayerClosed, iError);
+ PostFlowDownMessage(iError);
+
+ MaybePostDataClientIdle();
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::EtherFrame
+// -----------------------------------------------------------------------------
+//
+TInt CLANLinkCommon::EtherFrame(RMBufChain &aPdu, TDesC8& aDestAddr, TUint16 aType, TUint8& aDscp)
+ {
+ RMBufChain ethHdr;
+ TUint etherHeaderSize = (iEtherType==EStandardEthernet) ?
+ KEtherHeaderSize : KEtherLLCHeaderSize;
+
+ TRAPD(ret, ethHdr.AllocL(etherHeaderSize));
+ if(ret != KErrNone)
+ {
+ return ret;
+ }
+
+ TEtherLLCFrame *hdrBuf = reinterpret_cast<TEtherLLCFrame*>(ethHdr.First()->Buffer());
+
+ //Get the packet info:
+ RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(aPdu);
+
+ // Fill in the dest, src Mac addresses:
+ hdrBuf->SetDestAddr(aDestAddr);
+ hdrBuf->SetSrcAddr(iMacAddr);
+
+ switch(iEtherType)
+ {
+ case EStandardEthernet:
+ BigEndian::Put16((TUint8*)&hdrBuf->iType,aType);
+ break;
+ case ELLCEthernet:
+ // Several fields to fill in. According to nifmbuf.h,
+ // info->iLength gives the actual length of the packet.
+ BigEndian::Put16((TUint8*)&hdrBuf->iLen,static_cast<TInt16>(info->iLength));
+ hdrBuf->iDSAP=KLLC_SNAP_DSAP;
+ hdrBuf->iSSAP=KLLC_SNAP_SSAP;
+ hdrBuf->iCtrl=KLLC_SNAP_CTRL;
+ hdrBuf->SetOUI(0);
+ hdrBuf->SetType(aType);
+ break;
+ default:
+ // Can't handle any other kind of Ethernet header.
+ return KErrGeneral;
+ }
+
+ //Remove the original first Packet - by trimming the info from the packet.
+ aPdu.TrimStart(aPdu.Length() - info->iLength); // At this point, info becomes invalid.
+
+ //Extract the DSCP value as aPdu points to IP packet now
+ if (KIPFrameType == aType)
+ {
+ TInet6HeaderIP4 *ipv4hdr = (TInet6HeaderIP4 *)aPdu.First()->Ptr();
+ TUint8 TOS = ipv4hdr->TOS();
+ aDscp = (TOS >> 2) & 0xff;
+ DEBUG2( "CLanLinkCommon::EtherFrame() - DSCP of the IPv4 packet: 0x%02X (%u)",
+ aDscp, aDscp );
+ }
+ else if (KIP6FrameType == aType)
+ {
+ TInet6HeaderIP *ipv6hdr = (TInet6HeaderIP *)aPdu.First()->Ptr();
+ TUint8 TrafficClass = ipv6hdr->TrafficClass();
+ aDscp = (TrafficClass >> 2) & 0xff;
+ DEBUG2( "CLanLinkCommon::EtherFrame() - DSCP of the IPv6 packet: 0x%02X (%u)",
+ aDscp, aDscp );
+ }
+
+ //Finally, add the saved packet buffer to the mac header
+ aPdu.Prepend(ethHdr);
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::FrameSend
+// -----------------------------------------------------------------------------
+//
+TInt CLANLinkCommon::FrameSend(
+ RMBufChain& aPdu,
+ TDesC8& aDestAddr,
+ TUint16 aType )
+ {
+ // Call down from the Protocol
+ // The data begins in the second MBuf - because the first one
+ // is the info. The upper layer must have filled in the destination
+ // and source Mac addresses before this method is called and must
+ // supply the ether header type in aType.
+ // EtherFrame strips off the info and replaces it by the proper
+ // ether header.
+
+ TUint8 dscp( 0 );
+ TInt err = EtherFrame( aPdu, aDestAddr, aType, dscp );
+ if( err != KErrNone )
+ {
+ // drop the packet but _don't_ return an error (if we return
+ // an error from here, the stack thinks it is fatal...)
+ aPdu.Free();
+ return KContinueSending;
+ }
+
+ // Map DSCP values to desired access class and user priority values.
+ T8021DPriority userPriority( KDSCPtoUP[dscp] );
+ TWlmAccessClass accessClass( KUPtoAC[userPriority] );
+ TBool dropPacket( EFalse );
+
+ // ARP packets are treated as Voice traffic.
+ if( aType == KArpFrameType )
+ {
+ DEBUG( "CLanLinkCommon::FrameSend() - ARP packet" );
+
+ userPriority = E8021DUserPriorityNC;
+ accessClass = EWlmAccessClassVoice;
+ }
+
+ if( iAcArray[accessClass]->IsAdmitted() )
+ {
+ DEBUG1( "CLanLinkCommon::FrameSend() - traffic admitted on AC %u",
+ accessClass );
+ }
+ else
+ {
+ DEBUG1( "CLanLinkCommon::FrameSend() - traffic NOT admitted on AC %u",
+ accessClass );
+
+ // Find an admitted access class.
+ DownGradePacket( userPriority, dropPacket );
+ }
+
+ if( !dropPacket )
+ {
+ //Prepend UP value to the packet
+ RMBufChain UPBuf;
+ TRAPD( allocRet, UPBuf.AllocL( sizeof(TUint8) ) );
+ if( allocRet != KErrNone )
+ {
+ // drop the packet but _don't_ return an error (if we return
+ // an error from here, the stack thinks it is fatal...)
+ aPdu.Free();
+ return KContinueSending;
+ }
+
+ (UPBuf.First())->Put((TUint8)userPriority);
+ aPdu.Prepend( UPBuf );
+
+ DEBUG2( "CLanLinkCommon::FrameSend() - sending packet on AC %u with UP %u",
+ KUPtoAC[userPriority],
+ userPriority );
+ TInt ret = iPktDrv->Send( aPdu );
+
+ // ARP packets will never triggers traffic stream creation.
+ if( aType == KArpFrameType )
+ {
+ return ret;
+ }
+
+ // Notify the per-AC handler.
+ iAcArray[accessClass]->OnFrameSend();
+
+ if( ret != KContinueSending )
+ {
+ // Suspend inactivity timer for all ACs if NIF Queue is full.
+ for( TUint idx( 0 ); idx < EWlmAccessClassMax; ++idx )
+ {
+ iAcArray[idx]->SuspendInactivityTimer();
+ }
+ }
+
+ return ret;
+ }
+ else
+ {
+ DEBUG( "CLanLinkCommon::FrameSend() - no ACs admitted, dropping packet" );
+
+ aPdu.Free();
+
+ return KContinueSending;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::DownGradePacket
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::DownGradePacket(
+ T8021DPriority& aUP,
+ TBool& aDrop )
+ {
+ DEBUG1( "CLanLinkCommon::DownGradePacket() - UP before downgrade: %u",
+ aUP );
+
+ /**
+ * This method wouldn't be called if downgrade wasn't needed,
+ * so we don't have to check Voice priority at all.
+ */
+ TWlmAccessClass accessClass( KNextAC[KUPtoAC[aUP]] );
+ while( accessClass != EWlmAccessClassMax )
+ {
+ if( iAcArray[accessClass]->IsAdmitted() )
+ {
+ aUP = KACtoUP[accessClass];
+ aDrop = EFalse;
+
+ DEBUG1( "CLanLinkCommon::DownGradePacket() - UP after downgrade: %u",
+ aUP );
+
+ return;
+ }
+
+ accessClass = KNextAC[accessClass];
+ }
+
+ DEBUG( "CLanLinkCommon::DownGradePacket() - packet will be dropped" );
+
+ aDrop = ETrue;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::GetProtocolType
+// -----------------------------------------------------------------------------
+//
+TInt CLANLinkCommon::GetProtocolType(
+ TUint8* aEtherHeader,
+ TUint16& aEtherType )
+ {
+ TEtherFrame* etherFrame = reinterpret_cast<TEtherFrame*>(aEtherHeader);
+ TUint16 etherType = etherFrame->GetType();
+
+ if( etherType >= KMinEtherType)
+ {
+ // type/length field >= 1536, this is Ethernet II frame
+ aEtherType = etherType;
+ }
+ else
+ {
+ // type/length field is something between KEtherLLCMaxLengthFieldValue
+ // and KMinEtherType, this shouldn't happen...
+ //__ASSERT_DEBUG(EFalse, User::Panic(_L("wlannif"), KErrGeneral));
+ return KErrNotSupported;
+ }
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::Process
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::Process(
+ RMBufChain& aPdu,
+ TUint8* aEtherHeader,
+ TUint8 aUPValue )
+ {
+ TUint16 etherCode(0);
+ TBool packetProcessed(EFalse);
+ TInt ret=GetProtocolType( aEtherHeader, etherCode );
+ if( ret==KErrNone )
+ { // It's an ethernet packet of some kind.
+ DEBUG2("CLANLinkCommon::Process() - UP: %u, ethertype: 0x%04X",
+ aUPValue, etherCode );
+
+ TUint bearerLim = iBearers->Count();
+ for( TUint index=0;index<bearerLim && !packetProcessed; index++ )
+ {
+ CLanxBearer *bearer=(*iBearers)[index];
+
+ if( bearer->WantsProtocol(
+ etherCode, aPdu.First()->Next()->Buffer()) )
+ {
+ bearer->Process( aPdu );
+ packetProcessed=ETrue;
+ }
+ }
+ }
+ if( ret!=KErrNone || !packetProcessed )
+ {
+ aPdu.Free(); // Something strange about the packet - bin it
+ }
+ else
+ {
+ // Notify the per-AC handler.
+ iAcArray[KUPtoAC[aUPValue]]->OnFrameReceive();
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::ResumeSending
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CLANLinkCommon::ResumeSending()
+ {
+ DEBUG( "CLanLinkCommon::ResumeSending()" );
+
+ TUint bearerLim = iBearers->Count();
+ for( TUint index=0;index<bearerLim;index++ )
+ {
+ CLanxBearer *bearer=(*iBearers)[index];
+ bearer->StartSending( (CProtocolBase*)this );
+ }
+
+ for( TUint idx( 0 ); idx < EWlmAccessClassMax; ++idx )
+ {
+ iAcArray[idx]->ResumeInactivityTimer();
+ }
+ }
+
+/**
+
+*/
+EXPORT_C TInt CLANLinkCommon::ReadInt(const TDesC& /*aField*/, TUint32& /*aValue*/)
+{
+ return KErrNotSupported;
+}
+
+/**
+
+*/
+EXPORT_C TInt CLANLinkCommon::WriteInt(const TDesC& /*aField*/, TUint32 /*aValue*/)
+{
+ return KErrNotSupported;
+}
+
+/**
+
+*/
+EXPORT_C TInt CLANLinkCommon::ReadDes(const TDesC& /*aField*/, TDes8& /*aValue*/)
+{
+ return KErrNotSupported;
+}
+
+/**
+
+*/
+EXPORT_C TInt CLANLinkCommon::ReadDes(const TDesC& /*aField*/, TDes16& /*aValue*/)
+{
+ return KErrNotSupported;
+
+}
+
+/**
+
+*/
+EXPORT_C TInt CLANLinkCommon::WriteDes(const TDesC& /*aField*/, const TDesC8& /*aValue*/)
+{
+ return KErrNotSupported;
+}
+
+/**
+
+*/
+EXPORT_C TInt CLANLinkCommon::WriteDes(const TDesC& /*aField*/, const TDesC16& /*aValue*/)
+{
+ return KErrNotSupported;
+}
+
+/**
+
+*/
+EXPORT_C TInt CLANLinkCommon::ReadBool(const TDesC& /*aField*/, TBool& /*aValue*/)
+{
+ return KErrNotSupported;
+}
+
+/**
+
+*/
+EXPORT_C TInt CLANLinkCommon::WriteBool(const TDesC& /*aField*/, TBool /*aValue*/)
+{
+ return KErrNotSupported;
+}
+
+/**
+
+*/
+EXPORT_C void CLANLinkCommon::IfProgress(TInt aStage, TInt aError)
+{
+ PostProgressMessage(aStage, aError);
+}
+
+/**
+
+*/
+EXPORT_C void CLANLinkCommon::IfProgress(TSubConnectionUniqueId /*aSubConnectionUniqueId*/, TInt aStage, TInt aError)
+{
+ // Not quite correct - there is no subconnection id specific progress message.
+ IfProgress(aStage, aError);
+}
+
+/**
+
+*/
+EXPORT_C void CLANLinkCommon::NifEvent(TNetworkAdaptorEventType /*aEventType*/, TUint /*aEvent*/, const TDesC8& /*aEventData*/, TAny* /*aSource*/)
+{
+}
+
+// ======================================================================================
+//
+// from MFlowBinderControl
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::GetControlL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C MLowerControl* CLANLinkCommon::GetControlL(const TDesC8& aName)
+/**
+Request from upper CFProtocol to retrieve our MLowerControl class.
+
+@param aName Protocol Name. Presently, only "ip" and "ip6" are supported.
+@return pointer to our MLowerControl class instance. We leave on an error, hence this routine should
+never return NULL.
+*/
+ {
+ DEBUG("CLANLinkCommon::GetControlL()");
+
+ CLanxBearer* bearer=NULL;
+ if (aName.CompareF(KDescIp6) == 0)
+ {
+ bearer = new(ELeave) CLanIp6Bearer(this);
+ }
+ else if (aName.CompareF(KDescIp) == 0 || aName.CompareF(KDescIcmp) == 0)
+ {
+ bearer = new(ELeave) CLanIp4Bearer(this);
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ CleanupStack::PushL(bearer);
+ bearer->ConstructL();
+
+ iBearers->AppendL(bearer);
+ ProvisionBearerConfigL(aName);
+ CleanupStack::Pop();
+ return bearer;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::BindL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C MLowerDataSender* CLANLinkCommon::BindL(const TDesC8& aProtocol, MUpperDataReceiver* aReceiver, MUpperControl* aControl)
+/**
+Request from upper CFProtocol to bind to this module.
+
+@param aProtocol protocol name (e.g. "ip", "ip6" etc).
+@param aReceiver pointer to MUpperDataReceiver instance of upper CFProtocol
+@param aControl pointer to MUpperControl instance of upper CFProtocol
+@return pointer to our MLowerDataSender instance (eventually passed to the upper CFProtocol)
+*/
+ {
+ DEBUG("CLANLinkCommon::BindL()");
+
+ TInt index = 0;
+ CLanxBearer* bearer = FindBearerByProtocolName(aProtocol, index);
+ if (bearer)
+ {
+ bearer->SetUpperPointers(aReceiver, aControl);
+ if (iValidMacAddr)
+ {
+ aControl->StartSending();
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+ iSubConnectionProvider.RNodeInterface::PostMessage(Id(), TCFControlProvider::TActive().CRef());
+ return bearer;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::Unbind
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CLANLinkCommon::Unbind(MUpperDataReceiver* /*aReceiver*/, MUpperControl* aControl)
+/**
+Request from upper CFProtocol to unbind from this module.
+
+@param aReceiver pointer to data receiver class of upper CFProtocol (originally passed to it in downward BindL() request)
+@param aControl pointer to control class of upper CFProtocol (originally passed to it in downward BindL() request)
+*/
+
+ {
+ DEBUG("CLANLinkCommon::Unbind()");
+
+ TInt index = 0;
+ CLanxBearer* bearer = FindBearerByUpperControl(aControl, index);
+ ASSERT(bearer);
+ iBearers->Delete(index);
+ delete bearer;
+
+ // If no-one remains bound to us, signal data client idle to SCPR
+ MaybePostDataClientIdle();
+ }
+
+
+//
+// Utilities
+//
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::FindBearerByProtocolName
+// -----------------------------------------------------------------------------
+//
+CLanxBearer* CLANLinkCommon::FindBearerByProtocolName(const TDesC8& aProtocol, TInt& aIndex) const
+/**
+Search the iBearers array searching for a match by protocol name.
+
+@param aProtocol name of protocol (in)
+@param aIndex on success, index of found entry (>=0), else -1.
+@return pointer to CLanxBearer entry on success else NULL.
+*/
+ {
+ DEBUG("CLANLinkCommon::FindBearerByProtocolName()");
+
+ TInt count = iBearers->Count();
+ for (TInt i = 0 ; i < count ; ++i)
+ {
+ CLanxBearer* bearer = iBearers->At(i);
+ if (bearer->ProtocolName() == aProtocol)
+ {
+ aIndex = i;
+ return bearer;
+ }
+ }
+ aIndex = -1;
+ return NULL;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::FindBearerByUpperControl
+// -----------------------------------------------------------------------------
+//
+CLanxBearer* CLANLinkCommon::FindBearerByUpperControl(const MUpperControl* aUpperControl, TInt& aIndex) const
+/**
+Search the iBearers array searching for a match by protocol name.
+
+@param aProtocol name of protocol (in)
+@param aIndex on success, index of found entry (>=0), else -1.
+@return pointer to CLanxBearer entry on success else NULL.
+*/
+ {
+ DEBUG("CLANLinkCommon::FindBearerByUpperControl()");
+
+ TInt count = iBearers->Count();
+ for (TInt i = 0 ; i < count ; ++i)
+ {
+ CLanxBearer* bearer = iBearers->At(i);
+ if (bearer->MatchesUpperControl(aUpperControl))
+ {
+ aIndex = i;
+ return bearer;
+ }
+ }
+ aIndex = -1;
+ return NULL;
+ }
+
+// =====================================================================================
+//
+// MCFNode
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::ReceivedL
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CLANLinkCommon::ReceivedL(const TRuntimeCtxId& aSender, const TNodeId& aRecipient, TSignatureBase& aMessage)
+/**
+Routine called on an incoming message from SCPR
+
+@param aCFMessage incoming message
+@return KErrNone, else a system wide error code.
+*/
+ {
+ DEBUG1("CLANLinkCommon::ReceivedL(), aCFMessage=%d", aMessage.MessageId().MessageId());
+
+ CSubConnectionFlowBase::ReceivedL(aSender, aRecipient, aMessage);
+
+ if (TEBase::ERealmId == aMessage.MessageId().Realm())
+ {
+ switch (aMessage.MessageId().MessageId())
+ {
+ case TEBase::TError::EId :
+ SubConnectionError(static_cast<TEBase::TError&>(aMessage).iValue);
+ break;
+ case TEBase::TCancel::EId :
+ CancelStartFlow();
+ break;
+ default:
+ ASSERT(EFalse);
+ }
+ }
+ else if (TEChild::ERealmId == aMessage.MessageId().Realm())
+ {
+ switch (aMessage.MessageId().MessageId())
+ {
+ case TEChild::TDestroy::EId :
+ Destroy();
+ break;
+ default:
+ ASSERT(EFalse);
+ }
+ }
+ else if (TCFDataClient::ERealmId == aMessage.MessageId().Realm())
+ {
+ switch (aMessage.MessageId().MessageId())
+ {
+ case TCFDataClient::TStart::EId :
+ StartFlowL();
+ break;
+ case TCFDataClient::TProvisionConfig::EId:
+ ProvisionConfig(static_cast<TCFDataClient::TProvisionConfig&>(aMessage).iConfig);
+ break;
+ case TCFDataClient::TStop::EId :
+ StopFlow(static_cast<TCFDataClient::TStop&>(aMessage).iValue);
+ break;
+ case TCFDataClient::TBindTo::EId :
+ {
+ TCFDataClient::TBindTo& bindToReq = message_cast<TCFDataClient::TBindTo>(aMessage);
+ if (!bindToReq.iNodeId.IsNull())
+ {
+ User::Leave(KErrNotSupported);
+ }
+ RClientInterface::OpenPostMessageClose(Id(), aSender, TCFDataClient::TBindToComplete().CRef());
+ break;
+ }
+ default:
+ ASSERT(EFalse);
+ }
+ }
+ else if (TLinkMessage::ERealmId == aMessage.MessageId().Realm())
+ {
+ switch (aMessage.MessageId().MessageId())
+ {
+ case TLinkMessage::TAgentToFlowNotification::EId:
+ {
+ TLinkMessage::TAgentToFlowNotification& msg = message_cast<TLinkMessage::TAgentToFlowNotification>(aMessage);
+ if(msg.iValue != EAgentToNifEventVendorSpecific)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ else //EAgentToNifEventVendorSpecific
+ {
+ //User::LeaveIfError((iPktDrv) ? iPktDrv->Notification(
+ // static_cast<TAgentToNifEventType>(msg.iValue), NULL) : KErrNotSupported);
+ DEBUG("CLANLinkCommon::ReceivedL(), rcvd disconnect notification from Agent");
+ iError = KErrDisconnected;
+ StopInterface();
+ }
+ }
+ break;
+ default:
+ ASSERT(EFalse);
+ }; //endswitch
+ }
+ else
+ {
+ ASSERT(EFalse);
+ }
+ }
+
+//
+// Methods for handling incoming SCPR messages
+//
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::StartFlowL
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::StartFlowL()
+ {
+ DEBUG("CLANLinkCommon::StartFlowL()");
+
+ if ( !iPktDrv )
+ LoadPacketDriverL();
+
+ iStopRequested = EFalse;
+
+ ASSERT(iMMState == EStopped);
+
+ if (iSavedError != KErrNone)
+ {
+ // If there were errors during prior processing of the TProvisionConfig message,
+ // leave here and cause a TError response to TDataClientStart.
+ User::Leave(iSavedError);
+ }
+
+ iValidMacAddr = ReadMACSettings();
+
+ iMMState = EStarting;
+ User::LeaveIfError(iPktDrv->StartInterface());
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::CancelStartFlow
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::CancelStartFlow()
+ {
+ if (iMMState == EStarting)
+ {
+ iStopRequested = ETrue;
+
+ iPktDrv->StopInterface();
+ PostProgressMessage(KLinkLayerClosed, KErrCancel);
+ PostFlowDownMessage(KErrCancel);
+
+ MaybePostDataClientIdle();
+ }
+ }
+
+
+// half a second should be enough for sending DHCPRELEASE
+static const TInt KDhcpReleaseDelay = 500000;
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::StopFlow
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::StopFlow(TInt aError)
+ {
+ DEBUG("CLANLinkCommon::StopFlow()");
+
+ iStopRequested = ETrue;
+
+ iMMState = EStopping;
+
+ iError = aError;
+
+ TCallBack callback(StopCb, this);
+ TRAPD(err, iPeriodic = CPeriodic::NewL(CActive::EPriorityStandard));
+ if(err == KErrNone)
+ {
+ // Call the callback after KDhcpReleaseDelay. This is done only once,
+ // but we need to put something (KMaxTInt) to CPeriodic's interval.
+ iPeriodic->Start(TTimeIntervalMicroSeconds32(KDhcpReleaseDelay), TTimeIntervalMicroSeconds32(KMaxTInt), callback);
+ }
+ else
+ {
+ iPeriodic = NULL;
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::SubConnectionGoingDown
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::SubConnectionGoingDown()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::SubConnectionError
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::SubConnectionError(TInt /*aError*/)
+ {
+ }
+
+
+/*
+Provisioning description for Ethernet CFProtocol Flow:
+
+- on receipt of the TProvisionConfig message, the pointer contained within is stored
+ in iAccessPointConfig and the provisioning information contained within the AccessPointConfig
+ array is validated:
+ - at least one of TLanIp4Provision or TLanIp6Provision must be present. They are added by the EtherMCPr and
+ populated from CommsDat.
+
+- the packet driver is loaded.
+
+- if any of the above steps fail, the resulting error is saved in iSaveError so that when TDataClientStart message is
+ subsequently received, a TError message can be sent in response (there is no response to TProvisionConfig message).
+*/
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::ProvisionConfig
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::ProvisionConfig( const RMetaExtensionContainerC& aConfigData )
+ {
+ DEBUG("CLANLinkCommon::ProvisionConfig()");
+
+ iSavedError = KErrNone;
+
+ AccessPointConfig().Close();
+ AccessPointConfig().Open(aConfigData);
+
+ iLanIp4Provision = static_cast<const TLanIp4Provision*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(TLanIp4Provision::EUid, TLanIp4Provision::ETypeId)));
+ if (iLanIp4Provision)
+ {
+ DEBUG("CLANLinkCommon::ProvisionConfig() - IP4 config to be provisioned");
+ }
+
+ iLanIp6Provision = static_cast<const TLanIp6Provision*>(AccessPointConfig().FindExtension(STypeId::CreateSTypeId(TLanIp6Provision::EUid, TLanIp6Provision::ETypeId)));
+ if (iLanIp6Provision)
+ {
+ DEBUG("CLANLinkCommon::ProvisionConfig() - IP6 config to be provisioned");
+ }
+
+ if (iLanIp4Provision == NULL && iLanIp6Provision == NULL)
+ {
+ // At least one set of IP4/6 provisioning information must be present
+ iSavedError = KErrCorrupt;
+ return;
+ }
+
+ TRAPD(err, ProvisionConfigL());
+ if (err != KErrNone)
+ {
+ iSavedError = err;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::ProvisionConfigL
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::ProvisionConfigL()
+ {
+ DEBUG("CLANLinkCommon::ProvisionConfigL()");
+
+ // Provision Bearers
+ if (iBearers->Count())
+ {
+ ProvisionBearerConfigL(KDescIp());
+ ProvisionBearerConfigL(KDescIp6());
+ }
+
+ iWLMServerCommon = new (ELeave) CLANNifWLMServerCommon(this);
+ iWLMServerCommon->ConstructL();
+
+ TBool isAutomaticMgmt( ETrue );
+ CRepository* repository = NULL;
+ TRAP_IGNORE( repository = CRepository::NewL( KCRUidWlanDeviceSettingsRegistryId ) );
+ if( repository )
+ {
+ TInt temp( 0 );
+ TInt ret = repository->Get( KWlanAutomaticTrafficStreamMgmt, temp );
+ if( ret == KErrNone &&
+ !temp )
+ {
+ isAutomaticMgmt = EFalse;
+ }
+
+ delete repository;
+ repository = NULL;
+ }
+
+ for( TUint idx( 0 ); idx < EWlmAccessClassMax; ++idx )
+ {
+ iAcArray[idx] = CLANNifWLMServerPerAC::NewL(
+ static_cast<TWlmAccessClass>( idx ),
+ KTsInactivityTime[idx],
+ isAutomaticMgmt );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::Destroy
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::Destroy()
+ {
+ DEBUG("CLANLinkCommon::Destroy()");
+
+ ASSERT(iMMState==EStopped);
+ DeleteThisFlow();
+ }
+
+// Utility functions
+
+void CLANLinkCommon::ProvisionBearerConfigL(const TDesC8& aName)
+ {
+ DEBUG("CLANLinkCommon::ProvisionBearerConfigL()");
+
+ TInt index = -1;
+ CLanxBearer* bearer = FindBearerByProtocolName(aName, index);
+ if (bearer)
+ {
+ if (aName.CompareF(KDescIp) == 0)
+ {
+ if (iLanIp4Provision)
+ {
+ bearer->SetProvisionL(iLanIp4Provision); // CLanIp4Bearer
+ }
+ }
+ else if (aName.CompareF(KDescIp6) == 0)
+ {
+ if (iLanIp6Provision)
+ {
+ bearer->SetProvisionL(iLanIp6Provision); // CLanIp6Bearer
+ }
+ }
+ }
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::PostProgressMessage
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::PostProgressMessage(TInt aStage, TInt aError)
+ {
+ DEBUG("CLANLinkCommon::PostProgressMessage()");
+
+ //Be careful when sending TStateChange message as RNodeChannelInterface will override the activity id
+ iSubConnectionProvider.RNodeInterface::PostMessage(Id(), TCFMessage::TStateChange( Elements::TStateChange( aStage, aError) ).CRef());
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::SetAllowedBearer
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::SetAllowedBearer(CLanxBearer* aBearer)
+ {
+ iOnlyThisBearer = aBearer;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::BearereIsActive
+// -----------------------------------------------------------------------------
+//
+TBool CLANLinkCommon::BearerIsActive(CLanxBearer* aBearer)
+ {
+ if (!iOnlyThisBearer ||
+ aBearer == iOnlyThisBearer)
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::PostFlowDownMessage
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::PostFlowDownMessage(TInt aError)
+ {
+ DEBUG("CLANLinkCommon::PostFlowDownMessage()");
+
+ if (iMMState == EStopping)
+ {
+ iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStopped(aError).CRef());
+ }
+ else if (iMMState == EStarting)
+ {
+ iSubConnectionProvider.PostMessage(Id(), TEBase::TError(TCFDataClient::TStart::Id(), aError).CRef());
+ }
+ else if (iMMState == EStarted)
+ {
+ iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError).CRef());
+ }
+ iMMState = EStopped;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::PostFlowGoingDownMessage
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::PostFlowGoingDownMessage(TInt aError, MNifIfNotify::TAction /*aAction*/)
+ {
+ DEBUG("CLANLinkCommon::PostFlowGoingDownMessage()");
+
+ // TDataClientGoneDown only makes sense if the flow was actually started
+ ASSERT(iMMState == EStarted);
+ iMMState = EStopped;
+ iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TDataClientGoneDown(aError).CRef());
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::PostDataClientStartedMessage
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::PostDataClientStartedMessage()
+ {
+ DEBUG("CLANLinkCommon::PostDataClientStartedMessage()");
+
+ iMMState = EStarted;
+ iSubConnectionProvider.PostMessage(Id(), TCFDataClient::TStarted().CRef());
+ }
+
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::MaybePostDataClientIdle
+// -----------------------------------------------------------------------------
+//
+void CLANLinkCommon::MaybePostDataClientIdle()
+ {
+ DEBUG("CLANLinkCommon::MaybePostDataClientIdle()");
+
+ if (iBearers->Count() == 0 && iMMState == EStopped)
+ {
+ iSubConnectionProvider.PostMessage(Id(), TCFControlProvider::TIdle().CRef());
+ }
+ }
+
+
+void TEtherLLCFrame::SetDestAddr( TDesC8& aDest)
+{
+ DEBUG("TEtherLLCFrame::SetDestAddr()");
+
+ Mem::Copy(iDestAddr, aDest.Ptr(), KMACByteLength);
+}
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::SetSrcAddr
+// -----------------------------------------------------------------------------
+//
+void TEtherLLCFrame::SetSrcAddr(TDesC8& aSrc)
+{
+ DEBUG("TEtherLLCFrame::SetSrcAddr()");
+
+ Mem::Copy(iSrcAddr, aSrc.Ptr(), KMACByteLength);
+}
+
+// -----------------------------------------------------------------------------
+// CLANLinkCommon::SetOUI
+// -----------------------------------------------------------------------------
+//
+void TEtherLLCFrame::SetOUI(TUint32 aOUI)
+{
+ DEBUG("TEtherLLCFrame::SetOUI()");
+
+ //aOUI is in native order, but the result is
+ //always stored in network byte order.
+ //Can't use the bigendian methods, because
+ //they only work for 16 and 32 -bit items.
+ OUI[0] = (TUint8)((aOUI>>16)&0xff);
+ OUI[1] = (TUint8)((aOUI>>8)&0xff);
+ OUI[2] = (TUint8)(aOUI&0xff);
+}