--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/ipeventnotifier/src/ipeventnotifier.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,796 @@
+// Copyright (c) 2004-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:
+//
+
+/**
+ @file ipeventnotifier.cpp
+ @internalComponent
+*/
+
+
+#include <in_chk.h>
+#include <icmp6_hdr.h>
+#include <in_sock.h>
+#include <in_bind.h>
+#include "in6_opt.h"
+
+#include "ipeventnotifier.h"
+#include "HookLog.h"
+#include <networking/ipeventtypes.h>
+#include "ipeventnotifierinterface.h"
+#include "ipeventlistener.h"
+#include <comms-infras/idquerynetmsg.h>
+#include "DHCPUnicastTranslator.h"
+
+
+CIPEventNotifier* CIPEventNotifier::NewL()
+ {
+ CIPEventNotifier* self = new(ELeave) CIPEventNotifier();
+ CleanupStack::PushL(self);
+
+ self->ConstructL();
+
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+
+void CIPEventNotifier::ConstructL()
+ {
+ /**
+ * Create the address/interface listener.
+ */
+ iIPEventListener = new (ELeave) CIPEventListener(*this);
+ }
+
+
+CIPEventNotifier::CIPEventNotifier()
+ {
+ }
+
+
+
+CIPEventNotifier::~CIPEventNotifier()
+ {
+ iInterfaces.ResetAndDestroy();
+
+ delete iIPEventListener;
+
+ delete iDHCPUnicastTranslator;
+ }
+
+
+
+void CIPEventNotifier::BindL(CProtocolBase* aProtocol, TUint aId)
+ {
+ // Do sanity checks
+ //
+ if ((aId != KProtocolInet6Ip) || (aProtocol == this))
+ {
+ User::Leave(KErrArgument);
+ }
+
+ TUint ourId;
+ {
+ TServerProtocolDesc info;
+ Identify(&info);
+ ourId = info.iProtocol;
+ }
+
+ if (aId == ourId)
+ {
+ User::Leave(KErrArgument);
+ }
+
+ if ( iProtocolIPv6 != NULL )
+ {
+ if ( iProtocolIPv6 == aProtocol )
+ {
+ // We don't need to bind to the same protocol twice.
+ //
+ return;
+ }
+ else
+ {
+ // We don't want to bind to a different protocol either...
+ //
+ User::Leave(KErrAlreadyExists);
+ }
+ }
+
+ iProtocolIPv6 = (CProtocolInet6Binder*) aProtocol;
+
+ // Get a pointer to the event service.
+ //
+ ObtainEventService();
+
+ // Must always register hooks on startup, til the required
+ // initial values have been received.
+ //
+ RegisterHooksL();
+
+ // Create cache of interfaces known to IP stack
+ //
+ AddKnownInterfacesL();
+
+ /**
+ * Create owned hook to allow unicast DHCP packets to pass.
+ * Notice we are bypassing the standard mechanism for including
+ * another protocol hook (esk files), and are directly creating
+ * it here as it is needed for the same lifetime as IPEN itself.
+ */
+ if (iDHCPUnicastTranslator == NULL)
+ {
+ iDHCPUnicastTranslator = new (ELeave) CDHCPUnicastTranslator(*iProtocolIPv6);
+ }
+ // connect the hook to the stack..
+ iProtocolIPv6->BindL(iDHCPUnicastTranslator, BindForwardHook());
+
+ }
+
+
+
+void CIPEventNotifier::Unbind(CProtocolBase* aProtocol, TUint /* aId */)
+ {
+ if (iProtocolIPv6 != aProtocol)
+ {
+ return;
+ }
+
+ iProtocolIPv6->Unbind(iDHCPUnicastTranslator, 0);
+
+ UnregisterHooks();
+
+ iProtocolIPv6 = 0;
+ iEventService = 0;
+ }
+
+
+
+TInt CIPEventNotifier::GetOption(TUint aLevel, TUint aName,TDes8& aOption,CProtocolBase* aSourceProtocol)
+/**
+ * Performs one of the following actions, depending on the option name:
+ *
+ * KHandleAttach: Sets up IPEN to catch and publish events on the interface named in aOption.
+ * Session handle TUint (the pubsub address key) returned in first 4 bytes of aOption buffer.
+ *
+ * KHandleRelease: Tells IPEN to stop catching and publishing events to the given session handle
+ * Handle passed in as TUint in first 4 bytes of aOption buffer.
+ *
+ * @param aLevel: should be KSolInetIp for this protocol
+ * @param aName: see above
+ * @param aOption: in/out, dependent on option name. See above
+ * @return error status
+ *
+ */
+ {
+ (void) aLevel;
+ (void) aSourceProtocol;
+
+ TInt retVal = KErrNotSupported;
+
+ switch (aName)
+ {
+ case NetMessages::KHandleAttach:
+ {
+ TName buf;
+ buf.Copy( aOption );
+ TUint *out_handlenum = (TUint *)aOption.Ptr();
+ TRAPD(retval, *out_handlenum = OpenSessionL(buf));
+ return retval;
+ }
+
+ case NetMessages::KHandleRelease:
+ {
+ TUint *in_handle = (TUint *)aOption.Ptr();
+ TInt ret = CloseSession(*in_handle);
+ *in_handle = 0;
+ return ret;
+ }
+
+ default:
+ break;
+ }
+
+ return retVal ;
+ }
+
+
+
+TUint CIPEventNotifier::OpenSessionL(const TDesC& aIfName)
+/**
+ * Sets up IPEN to catch and publish events on the interface named by aIfName.
+ * Session handle TUint (the pubsub address key) is returned.
+ *
+ * @internalTechnology
+ */
+ {
+ // The IP stack's first interface, a dummy, has an empty name string.
+ // Therefore an empty string to open against would match this dummy
+ // interface! So we should report failure if a naughty client is trying to
+ // monitor events on an interface with an empty name string.
+ //
+ if(aIfName == KNullDesC)
+ {
+ LOG(
+ _LIT(KHookNotifyStr,"ERROR: client attempted to monitor interface with empty name");
+ HookLog::Printf( KHookNotifyStr );
+ )
+ User::Leave(KErrBadName);
+ }
+
+ TInt ifPos = FindPositionOfInterfaceByName(aIfName);
+
+ CIPEventNotifierInterface* iface = 0;
+
+ if(ifPos == KErrNotFound)
+ {
+ AddKnownInterfacesL();
+ ifPos = FindPositionOfInterfaceByName(aIfName);
+ User::LeaveIfError(ifPos);
+ }
+
+ iface = iInterfaces[ifPos];
+
+ if( AnyClientsCurrentlyInterested() == false )
+ {
+ RegisterHooksL();
+ }
+
+ __ASSERT_ALWAYS(iface , User::Leave(KErrCorrupt));
+ iface->IncreaseRefCount();
+
+ PublishLastKnownStates(iface);
+
+ LOG(
+ _LIT(KHookNotifyStr2,"CIPEventNotifier::OpenSessionL - now monitoring interface %S (pos #%d)");
+ HookLog::Printf(KHookNotifyStr2,&aIfName,ifPos);
+ )
+
+ return iface->GetInterfaceIndex(); // later we might create a session id and map it to i/f #
+ }
+
+
+TInt CIPEventNotifier::CloseSession(TUint aHandle)
+ {
+ TInt acIfPos = FindPositionOfInterface(aHandle);
+
+ if(acIfPos == KErrNotFound)
+ {
+ return KErrNotFound;
+ }
+
+ CIPEventNotifierInterface* acIf = iInterfaces[acIfPos];
+
+ acIf->DecreaseRefCount();
+
+ // shouldn't be more closes than news! naughty client.
+ __ASSERT_ALWAYS((acIf->GetRefCount() >= 0), User::Panic(_L("IPEN:CloseSession"),1));
+
+ LOG(
+ _LIT(KHookNotifyStr2,"CIPEventNotifier::CloseSession handle %d (pos #%d)");
+ HookLog::Printf(KHookNotifyStr2,aHandle,acIfPos);
+ )
+
+ if( AnyClientsCurrentlyInterested() == false )
+ {
+ UnregisterHooks();
+ }
+
+ return KErrNone;
+ }
+
+
+
+void CIPEventNotifier::AddInterfaceL(TUint32 aIfIndex, const TDesC& aIfName)
+ {
+ CIPEventNotifierInterface* newActIf = new (ELeave)CIPEventNotifierInterface(aIfIndex, aIfName);
+ CleanupStack::PushL( newActIf );
+ iInterfaces.AppendL(newActIf);
+ CleanupStack::Pop( newActIf );
+ }
+
+
+
+void CIPEventNotifier::AddKnownInterfacesL()
+ {
+ TUint bufsize = 2048;
+ HBufC8 *buffer = 0;
+ TInt exceed;
+ buffer = GetBuffer(buffer, bufsize);
+ User::LeaveIfNull(buffer);
+ TPtr8 bufdes = buffer->Des();
+
+ do
+ {
+ //-- get list of network interfaces
+ // if exceed>0, all interface could not fit into the buffer.
+ // In that case allocate a bigger buffer and retry.
+ // There should be no reason for this while loop to take more than 2 rounds.
+ bufdes.Set(buffer->Des());
+ exceed = iProtocolIPv6->GetOption(KSolInetIfQuery, KSoInetInterfaceInfo, bufdes);
+ if(exceed > 0)
+ {
+ bufsize += exceed * sizeof(TInetInterfaceInfo);
+ buffer = GetBuffer(buffer, bufsize);
+ User::LeaveIfNull(buffer);
+ }
+ } while (exceed > 0);
+
+ TOverlayArray<TInetInterfaceInfo> infoIface(bufdes);
+
+ TInt idx;
+ for(idx=0; idx < infoIface.Length(); ++idx)
+ {
+ TInetInterfaceInfo& iface = infoIface[idx];
+
+ if(FindPositionOfInterface(iface.iIndex) == KErrNotFound)
+ {
+ LOG(
+ TBuf<2048> tmpBuf;
+ tmpBuf.Format(_L("Detected new i/f: index:%d, name: "),iface.iIndex);
+ tmpBuf.Append(iface.iName);
+ tmpBuf.AppendFormat(_L(", state:%d, SMti:%d, RMtu:%d, SpeedMetric:%d, feat:%d,"),
+ iface.iState,iface.iSMtu,iface.iRMtu,iface.iSpeedMetric,iface.iFeatures/*,iface.iHwAddr*/);
+ HookLog::Printf(tmpBuf);
+ )
+
+ TRAP_IGNORE(AddInterfaceL(iface.iIndex,iface.iName));
+ }
+ }
+ LOG(LogKnownInterfaces());
+ delete buffer;
+ }
+
+
+HBufC8* CIPEventNotifier::GetBuffer(HBufC8* apBuf, TInt aBufLenRequired)
+ {
+ HBufC8* pBufResult = NULL;
+
+ if(aBufLenRequired <= 0 )
+ return NULL; //-- invalid argument
+
+ if(!apBuf)
+ {//-- the buffer is not allocated at all, try allocate it
+ pBufResult = HBufC8::New(aBufLenRequired);
+ }
+ else
+ {//-- the buffer is already allocated. Check its size and try to reallocate if
+ //-- required size is bigger than existing. Otherwise do nothing.
+
+ if(apBuf->Des().MaxSize() >= aBufLenRequired)
+ pBufResult = apBuf; //-- do nothing, existing buffer is big enough
+ else
+ { //-- delete and allocate new buffer to avoid data copying
+ delete apBuf;
+ pBufResult = HBufC8::New(aBufLenRequired);
+ }
+ }
+
+ return pBufResult;
+ }
+
+
+TInt CIPEventNotifier::FindPositionOfInterface(TUint32 aIfIndex) const
+ {
+ TInt i;
+ for( i=0 ; i<iInterfaces.Count() /*inline call*/ ; ++i )
+ {
+ if(iInterfaces[i]->GetInterfaceIndex() == aIfIndex)
+ {
+ return i;
+ }
+ }
+ return KErrNotFound;
+ }
+
+
+
+TInt CIPEventNotifier::FindPositionOfInterfaceByName(const TDesC& aIfName) const
+ {
+ TInt i;
+ for( i=0 ; i<iInterfaces.Count() ; ++i )
+ {
+ if(iInterfaces[i]->GetInterfaceName() == aIfName)
+ {
+ return i;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+
+CIPEventNotifierInterface* CIPEventNotifier::GetInterfaceWithIndexL(TInt aIpIfIndex)
+ {
+ TInt aIfPos;
+ aIfPos = FindPositionOfInterface(aIpIfIndex);
+ if(aIfPos < 0)
+ {
+ LOG (
+ _LIT(KHookNotifyStr,"ERROR: couldn't find interface %d. err %d");
+ HookLog::Printf( KHookNotifyStr,aIpIfIndex, aIfPos);
+ )
+ User::Leave(aIfPos);
+ }
+
+ return iInterfaces[aIfPos];
+ }
+
+
+TBool CIPEventNotifier::AnyClientsCurrentlyInterested(void) const
+ {
+#ifdef ALWAYS_PUBLISH_IP_EVENTS
+ return true;
+#else
+ TInt i;
+ for( i=0 ; i<iInterfaces.Count() ; ++i )
+ {
+ if(iInterfaces[i]->GetRefCount() != 0 ||
+ iInterfaces[i]->iMFlagReceived == 0 ||
+ iInterfaces[i]->iLinklocalAddressKnown == 0 )
+ // (We must always listen until we've received the M flag and a LL addr.
+ // This is because DHCP must have access to these events, even if it hasn't started yet.)
+ {
+ return true;
+ }
+ }
+ return false;
+#endif
+ }
+
+
+TBool CIPEventNotifier::ShouldPublishEvent(TUint aInterfaceIndex)
+ {
+ TInt aIfPos;
+ aIfPos = FindPositionOfInterface(aInterfaceIndex);
+ if(aIfPos == KErrNotFound)
+ {
+ LOG ( HookLog::Printf(_L("UNEXPECTED: Interface %d not yet known. Trying to find it"),aInterfaceIndex); )
+ TRAP_IGNORE(AddKnownInterfacesL())
+ aIfPos = FindPositionOfInterface(aInterfaceIndex);
+ if(aIfPos == KErrNotFound)
+ {
+ LOG ( HookLog::Printf(_L("VERY UNEXPECTED: Couldn't add interface %d"),aInterfaceIndex); )
+ return EFalse;
+ }
+ aIfPos = FindPositionOfInterface(aInterfaceIndex);
+ }
+
+#ifdef ALWAYS_PUBLISH_IP_EVENTS
+ return ETrue;
+#else
+ CIPEventNotifierInterface* aIf = iInterfaces[aIfPos];
+ // if the M flag / LL addr has not yet been received we should try to catch it
+ return( (aIf->iMFlagReceived == 0) ||
+ (aIf->iLinklocalAddressKnown == 0) ||
+ (aIf->GetRefCount() > 0) );
+
+#endif
+ }
+
+
+void CIPEventNotifier::InterfaceDetached(const TDesC & aName, CNifIfBase *aIf)
+ {
+ (void)aIf;
+ TInt pos = FindPositionOfInterfaceByName(aName);
+ LOG(
+ _LIT(KHookNotifyStr,"CIPEventNotifier::InterfaceDetached %S ptr=%08x [pos %d of %d interfaces]");
+ HookLog::Printf(KHookNotifyStr,&aName,aIf,pos,iInterfaces.Count());
+ )
+ if(pos != KErrNotFound)
+ {
+ CIPEventNotifierInterface* notIf = iInterfaces[pos];
+ delete notIf;
+ iInterfaces.Remove(pos);
+ }
+ LOG(LogKnownInterfaces());
+ }
+
+#ifdef _DEBUG
+void CIPEventNotifier::LogKnownInterfaces()
+ {
+ LOG(
+ _LIT(KHookNotifyHeader,"Dumping iInterfaces:");
+ HookLog::Printf(KHookNotifyHeader);
+ )
+
+ for(TInt i=0 ; i<iInterfaces.Count() ; ++i )
+ {
+ LOG(
+ _LIT(KHookNotifyStr,"\tPos %d: %S, stack's index %d");
+ TName name = iInterfaces[i]->GetInterfaceName();
+ TUint32 idx = iInterfaces[i]->GetInterfaceIndex();
+ HookLog::Printf(KHookNotifyStr, i, &name, idx);
+ )
+ }
+ }
+#endif
+
+
+void CIPEventNotifier::RegisterHooksL(void)
+/**
+ * Registers the hook to catch IP stack events
+ */
+ {
+ if(!(iProtocolIPv6 && iEventService && iIPEventListener))
+ {
+ User::Leave(KErrNotReady);
+ }
+
+ // bind to IP for incoming packets
+ iProtocolIPv6->BindL((CProtocolBase*)this, BindHookAll());
+
+
+ // Register our listener class with the event service. We're interested in:
+ //
+ // i. address events
+ // for determining when DAD has completed and when link-local addresses have been assigned
+ // to an interface.
+ // ii. interface events to allow the notifier to associate interface names with the stack's
+ // internal indices.
+ //
+ iEventService->RegisterListener(iIPEventListener, EClassAddress);
+ iEventService->RegisterListener(iIPEventListener, EClassInterface);
+ }
+
+
+
+void CIPEventNotifier::UnregisterHooks(void)
+/**
+ * Detaches this hook from the running of the stack.
+ * This is so IPEN doesn't slow down the stack while it isn't
+ * needed by any clients.
+ *
+ * e.g. without this mechanism, every incoming packet would pass through
+ * CIPEventNotifier::ApplyL pointlessly.
+ *
+ */
+ {
+ if(!(iProtocolIPv6 && iEventService && iIPEventListener))
+ {
+ return;
+ }
+
+ // If IPv6 exists, unbind the hook. Covers both in/out hooks (I hope)
+ iProtocolIPv6->Unbind(this);
+
+ // Unregister the address/interface listener.
+ iEventService->RemoveListener(iIPEventListener);
+ }
+
+
+
+void CIPEventNotifier::FillIdentification(TServerProtocolDesc& anEntry)
+/**
+ * Fills in an existing protocol description structure with details of this protocol.
+ *
+ * @param aProtocolDesc: reference to the structure to be filled in
+ */
+ {
+ anEntry.iName=_S("ipen");
+ anEntry.iAddrFamily=KAfInet; //KAfExain;
+ anEntry.iSockType=KSockDatagram;
+ anEntry.iProtocol=KProtocolId;
+ anEntry.iVersion=TVersion(1, 0, 0);
+ anEntry.iByteOrder=EBigEndian;
+ anEntry.iServiceInfo=KSIDatagram | KSIConnectionLess;
+ anEntry.iNamingServices=0;
+ anEntry.iSecurity=KSocketNoSecurity;
+ anEntry.iMessageSize=0xffff;
+ anEntry.iServiceTypeInfo=0; // 1 for ability to create sockets
+ anEntry.iNumSockets=KUnlimitedSockets;
+ }
+
+
+void CIPEventNotifier::Identify(TServerProtocolDesc* aProtocolDesc) const
+/**
+ * Fills in an existing protocol description structure with details of this protocol.
+ *
+ * @param aProtocolDesc: pointer to the structure to be filled in
+ */
+ {
+ FillIdentification(*aProtocolDesc);
+ }
+
+
+TInt CIPEventNotifier::DefineProperty(Meta::SMetaData& aEvent, TUint aHandle)
+ {
+ TSecurityPolicy readPol(TSecurityPolicy::EAlwaysPass);
+ _LIT_SECURE_ID(ipeventsid,0x102045B9);
+ _LIT_SECURITY_POLICY_S0(writePol,ipeventsid);
+
+ TInt err = iPublisher.Define(TUid::Uid(aEvent.GetTypeId().iType), aHandle,
+ RProperty::EByteArray/*, readPol, writePol*/);
+
+ // Does not matter if property has already been defined - we ignore the error.
+ if( err == KErrAlreadyExists )
+ {
+ err = KErrNone;
+ }
+
+ return err;
+ }
+
+
+void CIPEventNotifier::PublishToHandle(TUint aHandle, Meta::SMetaData& aData)
+ {
+ TBuf8<RProperty::KMaxPropertySize> buf;
+
+ TInt res = aData.Store(buf);
+ if(res != KErrNone)
+ {
+ LOG(HookLog::Printf( _L("IPEN can't store: %d"), res));
+ return;
+ }
+
+ TPtrC8 toSet = buf;
+ res = iPublisher.Set(TUid::Uid(aData.GetTypeId().iType), aHandle, toSet);
+ if(res != KErrNone)
+ {
+ LOG(HookLog::Printf( _L("IPEN can't publish: %d"), res));
+ }
+ }
+
+
+
+/**
+ * Incoming packet
+ */
+TInt CIPEventNotifier::ApplyL(RMBufHookPacket& aPacket, RMBufRecvInfo& aInfo)
+ {
+
+ LOG (
+ _LIT(KHookNotifyStr,"CIPEventNotifier::ApplyL hit with protocol: %d");
+ HookLog::Printf( KHookNotifyStr , aInfo.iProtocol );
+ )
+
+ if(aInfo.iProtocol == static_cast<TInt>(KProtocolInet6Icmp) && // quickest first
+ ShouldPublishEvent(aInfo.iInterfaceIndex) )
+ {
+
+ LOG (
+ _LIT(KHookNotifyStr," ICMPv6 packet detected");
+ HookLog::Printf( KHookNotifyStr );
+ )
+
+ /**
+ * Could switch on ICMP type here, in case the hook needs to catch
+ * other ICMP packet types..
+ */
+ TInet6Checksum<TInet6HeaderICMP_RouterAdv> icmp(aPacket,aInfo.iOffset);
+
+ if(icmp.iHdr)
+ {
+ if (icmp.iHdr->Type() == KInet6ICMP_RouterAdv &&
+ icmp.VerifyChecksum( aPacket,
+ aInfo.iProtocol == static_cast<TInt>(KProtocolInet6Icmp) ? &aInfo : NULL,
+ aInfo.iOffset) )
+ {
+ TBool mflag = (icmp.iHdr->M() ? ETrue : EFalse) ;
+ TBool oflag = (icmp.iHdr->O() ? ETrue : EFalse) ;
+
+ LOG (
+ _LIT(KHookNotifyStr," IP EVENT on if# %d: Publishing M flag: %d");
+ HookLog::Printf( KHookNotifyStr, aInfo.iInterfaceIndex, mflag );
+ _LIT(KHookOFlagNotifyStr," IP EVENT on if# %d: Publishing O flag: %d");
+ HookLog::Printf( KHookOFlagNotifyStr, aInfo.iInterfaceIndex, oflag );
+ )
+
+ TRAPD(err, PublishMFlagL(aInfo.iInterfaceIndex, mflag, oflag));
+ if(err!=KErrNone)
+ {
+ LOG (
+ _LIT(KLogStr, "Can't publish M and O flags message! Err %d\n");
+ HookLog::Printf(KLogStr, err);
+ )
+ }
+ }
+ }
+
+ }
+
+ return KIp6Hook_PASS; // ensure we don't affect the control flow
+ }
+
+
+
+void CIPEventNotifier::ObtainEventService()
+ {
+ MInterfaceManager* ifacer = iProtocolIPv6->NetworkService()->Interfacer();
+
+ TRAPD(err, iEventService = IMPORT_API_L (ifacer, MEventService));
+ if (err != KErrNone)
+ {
+ LOG (
+ _LIT(KHookNotifyStr, "MEventService not available (%d). Some features may be missing\n");
+ HookLog::Printf(KHookNotifyStr, err);
+ )
+ }
+ }
+
+
+
+
+void CIPEventNotifier::PublishMFlagL(TInt aIpIfIndex, TBool aMflag, TBool aOflag)
+ {
+ CIPEventNotifierInterface* iface = GetInterfaceWithIndexL(aIpIfIndex);
+
+ if(iface)
+ {
+ if(iface->iMFlagReceived == 0)
+ {
+ iface->iMFlagReceived = CMFlagReceived::NewL();
+ User::LeaveIfError(DefineProperty(*(iface->iMFlagReceived), aIpIfIndex));
+ }
+
+ iface->iMFlagReceived->SetMFlag(aMflag);
+ iface->iMFlagReceived->SetOFlag(aOflag);
+ PublishToHandle(aIpIfIndex, *(iface->iMFlagReceived));
+ }
+ }
+
+
+void CIPEventNotifier::PublishIPReadyL(TInt aIpIfIndex, const TInetAddr& tmpInetAddr, TBool addressValid)
+ {
+ CIPEventNotifierInterface* iface = GetInterfaceWithIndexL(aIpIfIndex);
+
+ if(iface)
+ {
+ if(iface->iIPReady == 0)
+ {
+ iface->iIPReady = CIPReady::NewL();
+ User::LeaveIfError(DefineProperty(*(iface->iIPReady), aIpIfIndex));
+ }
+
+ iface->iIPReady->SetIPAddress(tmpInetAddr);
+ iface->iIPReady->SetAddressValid(addressValid);
+ PublishToHandle(aIpIfIndex, *(iface->iIPReady));
+ }
+ }
+
+void CIPEventNotifier::PublishLinklocalAddressKnownL(TInt aIpIfIndex, const TInetAddr& tmpInetAddr)
+ {
+ CIPEventNotifierInterface* iface = GetInterfaceWithIndexL(aIpIfIndex);
+
+ if(iface)
+ {
+ if(iface->iLinklocalAddressKnown == 0)
+ {
+ iface->iLinklocalAddressKnown = CLinklocalAddressKnown::NewL();
+ User::LeaveIfError(DefineProperty(*(iface->iLinklocalAddressKnown), aIpIfIndex));
+ }
+ iface->iLinklocalAddressKnown->SetIPAddress(tmpInetAddr);
+ PublishToHandle(aIpIfIndex, *(iface->iLinklocalAddressKnown));
+ }
+ }
+
+
+void CIPEventNotifier::PublishLastKnownStates(CIPEventNotifierInterface* aIface)
+{
+ TUint32 ifIdx = aIface->GetInterfaceIndex();
+
+ // For each message from which we need state, not just events
+ // i.e. everything that might happen before DHCP starts and registers
+ //
+ if(aIface->iMFlagReceived)
+ {
+ PublishToHandle(ifIdx, *(aIface->iMFlagReceived));
+ }
+ if(aIface->iLinklocalAddressKnown)
+ {
+ PublishToHandle(ifIdx, *(aIface->iLinklocalAddressKnown));
+ }
+}