--- a/networkingtestandutils/ipprobe/src/prt.cpp Fri May 14 17:24:38 2010 +0300
+++ b/networkingtestandutils/ipprobe/src/prt.cpp Thu May 27 14:26:17 2010 +0300
@@ -1,34 +1,50 @@
-// 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:
-// prt.cpp - Packet Probe Hook
-//
+/*
+* Copyright (c) 2009-2010 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: Packet probe hook
+*
+*/
#include <e32std.h>
#include <e32base.h>
+#include <f32file.h>
+#include <e32svr.h>
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <es_prot_internal.h>
#endif
+
#include "family.h"
#include "prt.h"
#include "sap.h"
#include "inet6log.h"
+_LIT(KTcpDumpFolder, "tcpdump\\");
+_LIT(KProbeDumpFile, "probe.cap");
+_LIT(KLogFolder, "c:\\logs\\");
-CProtocolProbe::CProtocolProbe(TUint aId) : iId(aId)
+CProtocolProbe::CProtocolProbe(TUint aId) :
+iId(aId),
+iDumpCb(CActive::EPriorityStandard),
+iFileServerOpen(EFalse),
+iFileOpen(EFalse),
+iBufCreated(EFalse)
{
LOG(Log::Printf(_L("Probe::CProtocolProbe()\r\n"));)
+ iTimeOrigin.UniversalTime();
+
+ TCallBack cbFunc(DumpCb, this);
+ iDumpCb.Set(cbFunc);
}
void CProtocolProbe::InitL(TDesC& aTag)
@@ -37,7 +53,6 @@
CProtocolBase::InitL(aTag);
}
-
void CProtocolProbe::StartL()
{
// __ASSERT_DEBUG(iProtocol != NULL, User::Leave(KErrGeneral));
@@ -45,20 +60,39 @@
CProtocolProbe::~CProtocolProbe()
{
- LOG(Log::Printf(_L("Probe::~CProtocolProbe()\r\n"));)
+ LOG(Log::Printf(_L("Probe::~CProtocolProbe()\r\n"));)
+ if(iFileOpen)
+ {
+ iFile.Close();
+ iFileOpen = EFalse;
+ }
+ if(iFileServerOpen)
+ {
+ iFs.Close();
+ iFileServerOpen = EFalse;
+ }
+ if(iBufCreated)
+ {
+ iBuf.Close();
+ iBufCreated = EFalse;
+ }
}
-
CProtocolProbe *CProtocolProbe::NewL(TUint aId)
{
+
return new (ELeave) CProtocolProbe(aId);
}
void CProtocolProbe::FillIdentification(TServerProtocolDesc& anEntry, TUint aId)
{
+
anEntry.iName=_S("probe");
if (aId > 1)
+ {
anEntry.iName.AppendNum(aId-1);
+ }
+
anEntry.iAddrFamily = KAfProbe;
anEntry.iSockType = KSockDatagram;
anEntry.iProtocol = aId;
@@ -83,7 +117,10 @@
LOG(Log::Printf(_L("Probe::NewSAPL(%d)\r\n"), aProtocol);)
if (aProtocol != KSockDatagram)
+ {
User::Leave(KErrNotSupported);
+ }
+
CProviderProbe* sap = new (ELeave) CProviderProbe(this);
sap->iNext = iList;
iList = sap;
@@ -97,6 +134,7 @@
//
void CProtocolProbe::CancelSAP(const CServProviderBase* aSAP)
{
+
CProviderProbe **h, *sap;
for (h = &iList; (sap = *h) != NULL; h = &sap->iNext)
if (sap == aSAP)
@@ -106,49 +144,218 @@
}
}
-
// CProtocolProbe::NetworkAttachedL
// ********************************
// When network becomes available, do the hooking!
//
void CProtocolProbe::NetworkAttachedL()
{
+
NetworkService()->BindL(this, MIp6Hook::BindPostHook());
NetworkService()->BindL(this, MIp6Hook::BindPostHook()+1);
+
+ // initialise dump file
+ if(iFileOpen)
+ {
+ iFile.Close();
+ iFileOpen = EFalse;
+ }
+ if(iFileServerOpen)
+ {
+ iFs.Close();
+ iFileServerOpen = EFalse;
+ }
+
+ User::LeaveIfError(iFs.Connect());
+ iFileServerOpen = ETrue;
+ TBuf<50> filename;
+ filename.Append(KLogFolder);
+ filename.Append(KTcpDumpFolder);
+ filename.Append(KProbeDumpFile);
+ User::LeaveIfError(iFile.Replace(iFs, filename, EFileWrite));
+ iFileOpen = ETrue;
+
+ // allocate buffer
+ if(!iBufCreated)
+ {
+ const TInt KMaxBufferSize = 65535;
+ iBuf.CreateL(KMaxBufferSize);
+ iBufCreated = ETrue;
+ }
+
+ LibcapDumpFileHeader();
}
+void CProtocolProbe::Queue(RMBufChain &aPacket)
//
-// CProtocolProbe::Deliver
-// ***********************
-// Generate a copy of the packet to every bound provider
+// Takes a copy of aPacket, adds it to the queue and triggers the callback
//
-void CProtocolProbe::Deliver(RMBufChain &aPacket)
{
- const RMBufPktInfo *const info = RMBufPacketBase::PeekInfoInChain(aPacket);
+
+ RMBufPacketBase copy;
+ TRAPD(err, copy.CopyPackedL(aPacket));
+ if (err == KErrNone)
+ {
+
+ //
+ // Calculate packet time-stamp
+ //
+ TTime newTime;
+ newTime.UniversalTime();
+ TTimeIntervalMicroSeconds interval = newTime.MicroSecondsFrom(iTimeOrigin);
+
+ const TInt KMicrosInASecond = 1000000;
- for (CProviderProbe* sap = iList; sap != NULL; sap = sap->iNext)
+ //TUint32 micros = interval.Int64().Low();
+ TUint32 micros = I64LOW(interval.Int64());//.Low(); x.Low() -> I64LOW(x)
+ TUint32 secs = micros / KMicrosInASecond;
+ micros -= (secs * KMicrosInASecond);
+
+ //
+ // Reuse the protocol and flags fields of
+ // RMBufPktInfo to store the time-stamp
+ //
+ RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(copy);
+ info->iProtocol = static_cast<TInt>(secs);
+ info->iFlags = static_cast<TUint>(micros);
+
+ iQueue.Append(copy);
+ iDumpCb.CallBack();
+ }
+ else
{
- if (sap->IsReceiving(*info))
- {
- RMBufPacketBase copy;
- TRAPD(err, copy.CopyPackedL(aPacket));
- if (err == KErrNone)
- sap->Process(copy, this);
- else
- copy.Free();
- }
+ copy.Free();
}
}
+//
+// CProtocolProbe::Dump
+// ***********************
+// Log the packet to file
+//
+void CProtocolProbe::Dump(RMBufChain &aPacket)
+ {
+
+ RMBufPacket packet;
+ packet.Assign(aPacket);
+ RMBufPktInfo* info = packet.Unpack();
+
+ TUint32 secs = static_cast<TUint32>(info->iProtocol);
+ TUint32 micros = static_cast<TUint32>(info->iFlags);
+
+ iBuf.SetMax();
+ packet.CopyOut(iBuf, 0);
+ if(iBuf.Length() != info->iLength)
+ {
+ iBuf.SetLength(info->iLength);
+ }
+ LibcapDump(iBuf, secs, micros);
+ packet.Free();
+ }
+
TInt CProtocolProbe::Send(RMBufChain &aPacket, CProtocolBase* aSrc)
{
- Deliver(aPacket);
+
+ Queue(aPacket);
return CProtocolPosthook::Send(aPacket, aSrc);
}
void CProtocolProbe::Process(RMBufChain &aPacket, CProtocolBase* aSrc)
{
- Deliver(aPacket);
+
+ Queue(aPacket);
CProtocolPosthook::Process(aPacket, aSrc);
}
+
+void CProtocolProbe::LibcapDumpFileHeader()
+//
+// Dump file header in a format compatible with Libcap
+//
+// Format is:
+//
+// struct FileHeader
+// {
+// TUint32 magic;
+// TUint16 version_major;
+// TUint16 version_minor;
+// TUint32 thiszone; /* gmt to local correction */
+// TUint32 sigfigs; /* accuracy of timestamps */
+// TUint32 snaplen; /* max length saved portion of each pkt */
+// TUint32 linktype; /* data link type (LINKTYPE_*) */
+// };
+//
+// Note LINKTYPE specified in libpcap/bpf/net/bpf.h (see www.tcpdump.org)
+//
+ {
+
+ TBuf8<sizeof(TUint32)*5+sizeof(TUint16)*2> fileHeader;
+ *((TUint32*) &(fileHeader.Ptr()[0])) = 0xa1b2c3d4;
+ *((TUint16*) &(fileHeader.Ptr()[4])) = 0x02;
+ *((TUint16*) &(fileHeader.Ptr()[6])) = 0x04;
+ *((TUint32*) &(fileHeader.Ptr()[8])) = 0x00;
+ *((TUint32*) &(fileHeader.Ptr()[12])) = 0x00;
+ *((TUint32*) &(fileHeader.Ptr()[16])) = 0xffff;
+ *((TUint32*) &(fileHeader.Ptr()[20])) = 12; // DLT_RAW 12 /* raw IP */
+ fileHeader.SetLength(fileHeader.MaxLength());
+
+ iFile.Write(fileHeader);
+ }
+
+void CProtocolProbe::LibcapDump(const TDesC8& aBuffer, TUint32 aTimeStampSecs, TUint32 aTimeStampMicros)
+//
+// Dumps a packet in a format compatbible with Libcap
+//
+// For each record the format is:
+//
+// struct record
+// {
+// TUint32 sec; /* time stamp - secs*/
+// TUint32 usec; /* time stamp - microsecs*/
+// TUint32 captureLen; /* length packet captured */
+// TUint32 packetLen; /* total length of packet*/
+// };
+//
+// Byte ordering of the header is little endian
+// Byte ordering of the packet is network byte order (big endian)
+//
+ {
+
+ TBuf8<sizeof(TUint32)*4> recordHeader;
+ recordHeader.FillZ();
+
+ *((TUint32*) &(recordHeader.Ptr()[0])) = aTimeStampSecs;
+ *((TUint32*) &(recordHeader.Ptr()[4])) = aTimeStampMicros;
+ *((TUint32*) &(recordHeader.Ptr()[8])) = aBuffer.Length();
+ *((TUint32*) &(recordHeader.Ptr()[12])) = aBuffer.Length();
+ recordHeader.SetLength(recordHeader.MaxLength());
+
+ iFile.Write(recordHeader);
+ iFile.Write(aBuffer);
+ }
+
+
+
+TInt CProtocolProbe::DumpCb(TAny* aThisPtr)
+//
+// Callback function - calls DumpQueuedPackets()
+//
+ {
+
+ CProtocolProbe* self = static_cast<CProtocolProbe*>(aThisPtr);
+ self->DumpQueuedPackets();
+ return KErrNone;
+ }
+
+void CProtocolProbe::DumpQueuedPackets()
+//
+// Dumps all packets on the queue to the log file
+//
+ {
+
+ RMBufPacketBase packet;
+ while(iQueue.Remove(packet))
+ {
+ Dump(packet);
+ }
+ }