networkingtestandutils/ipprobe/src/prt.cpp
changeset 25 d15a50675083
parent 0 af10295192d8
child 58 8d540f55e491
equal deleted inserted replaced
20:e8d041006974 25:d15a50675083
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     1 /*
     2 // All rights reserved.
     2 * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). 
     3 // This component and the accompanying materials are made available
     3 * All rights reserved.
     4 // under the terms of "Eclipse Public License v1.0"
     4 * This component and the accompanying materials are made available
     5 // which accompanies this distribution, and is available
     5 * under the terms of "Eclipse Public License v1.0"
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     6 * which accompanies this distribution, and is available
     7 //
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 // Initial Contributors:
     8 *
     9 // Nokia Corporation - initial contribution.
     9 * Initial Contributors:
    10 //
    10 * Nokia Corporation - initial contribution.
    11 // Contributors:
    11 *
    12 //
    12 * Contributors:
    13 // Description:
    13 *
    14 // prt.cpp - Packet Probe Hook
    14 * Description: Packet probe hook
    15 //
    15 *
       
    16 */
    16 
    17 
    17 #include <e32std.h>
    18 #include <e32std.h>
    18 #include <e32base.h>
    19 #include <e32base.h>
       
    20 #include <f32file.h>
       
    21 #include <e32svr.h>
    19 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
    22 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
    20 #include <es_prot_internal.h>
    23 #include <es_prot_internal.h>
    21 #endif
    24 #endif
       
    25 
    22 
    26 
    23 #include "family.h"
    27 #include "family.h"
    24 #include "prt.h"
    28 #include "prt.h"
    25 #include "sap.h"
    29 #include "sap.h"
    26 #include "inet6log.h"
    30 #include "inet6log.h"
    27 
    31 _LIT(KTcpDumpFolder, "tcpdump\\");
    28 
    32 _LIT(KProbeDumpFile, "probe.cap");
    29 CProtocolProbe::CProtocolProbe(TUint aId) : iId(aId)
    33 _LIT(KLogFolder,     "c:\\logs\\");
       
    34 
       
    35 
       
    36 CProtocolProbe::CProtocolProbe(TUint aId) : 
       
    37 iId(aId), 
       
    38 iDumpCb(CActive::EPriorityStandard),
       
    39 iFileServerOpen(EFalse),
       
    40 iFileOpen(EFalse),
       
    41 iBufCreated(EFalse)
    30 	{
    42 	{
    31 	LOG(Log::Printf(_L("Probe::CProtocolProbe()\r\n"));)
    43 	LOG(Log::Printf(_L("Probe::CProtocolProbe()\r\n"));)
       
    44 	iTimeOrigin.UniversalTime();
       
    45 
       
    46 	TCallBack cbFunc(DumpCb, this);
       
    47 	iDumpCb.Set(cbFunc);
    32 	}
    48 	}
    33 
    49 
    34 void CProtocolProbe::InitL(TDesC& aTag)
    50 void CProtocolProbe::InitL(TDesC& aTag)
    35 	{
    51 	{
    36 	LOG(Log::Printf(_L("Probe::InitL()\r\n"));)
    52 	LOG(Log::Printf(_L("Probe::InitL()\r\n"));)
    37 	CProtocolBase::InitL(aTag);
    53 	CProtocolBase::InitL(aTag);
    38 	}
    54 	}
    39 
    55 
    40 
       
    41 void CProtocolProbe::StartL()
    56 void CProtocolProbe::StartL()
    42 	{
    57 	{
    43 	//	__ASSERT_DEBUG(iProtocol != NULL, User::Leave(KErrGeneral));
    58 	//	__ASSERT_DEBUG(iProtocol != NULL, User::Leave(KErrGeneral));
    44 	}
    59 	}
    45 
    60 
    46 CProtocolProbe::~CProtocolProbe()
    61 CProtocolProbe::~CProtocolProbe()
    47 	{
    62 	{
    48 	LOG(Log::Printf(_L("Probe::~CProtocolProbe()\r\n"));)
    63 	LOG(Log::Printf(_L("Probe::~CProtocolProbe()\r\n"));)	
    49 	}
    64 	if(iFileOpen)
    50 
    65 	    {
       
    66 		iFile.Close();
       
    67 		iFileOpen = EFalse;
       
    68 	    }
       
    69 	if(iFileServerOpen)
       
    70 		{
       
    71 		iFs.Close();
       
    72 		iFileServerOpen = EFalse;
       
    73 		}	
       
    74     if(iBufCreated)
       
    75         {
       
    76         iBuf.Close();
       
    77         iBufCreated = EFalse;
       
    78         }
       
    79 	}
    51 
    80 
    52 CProtocolProbe *CProtocolProbe::NewL(TUint aId)
    81 CProtocolProbe *CProtocolProbe::NewL(TUint aId)
    53 	{
    82 	{
       
    83 
    54 	return new (ELeave) CProtocolProbe(aId);
    84 	return new (ELeave) CProtocolProbe(aId);
    55 	}
    85 	}
    56 
    86 
    57 void CProtocolProbe::FillIdentification(TServerProtocolDesc& anEntry, TUint aId)
    87 void CProtocolProbe::FillIdentification(TServerProtocolDesc& anEntry, TUint aId)
    58 	{
    88 	{
       
    89 
    59 	anEntry.iName=_S("probe");
    90 	anEntry.iName=_S("probe");
    60 	if (aId > 1)
    91 	if (aId > 1)
       
    92 		{
    61 		anEntry.iName.AppendNum(aId-1);
    93 		anEntry.iName.AppendNum(aId-1);
       
    94 		}
       
    95 
    62 	anEntry.iAddrFamily = KAfProbe;
    96 	anEntry.iAddrFamily = KAfProbe;
    63 	anEntry.iSockType = KSockDatagram;
    97 	anEntry.iSockType = KSockDatagram;
    64 	anEntry.iProtocol = aId;
    98 	anEntry.iProtocol = aId;
    65 	anEntry.iVersion = TVersion(1, 0, 0);
    99 	anEntry.iVersion = TVersion(1, 0, 0);
    66 	anEntry.iByteOrder = EBigEndian;
   100 	anEntry.iByteOrder = EBigEndian;
    81 CServProviderBase* CProtocolProbe::NewSAPL(TUint aProtocol)
   115 CServProviderBase* CProtocolProbe::NewSAPL(TUint aProtocol)
    82 	{
   116 	{
    83 	LOG(Log::Printf(_L("Probe::NewSAPL(%d)\r\n"), aProtocol);)
   117 	LOG(Log::Printf(_L("Probe::NewSAPL(%d)\r\n"), aProtocol);)
    84 
   118 
    85 	if (aProtocol != KSockDatagram)
   119 	if (aProtocol != KSockDatagram)
       
   120 		{
    86 		User::Leave(KErrNotSupported);
   121 		User::Leave(KErrNotSupported);
       
   122 		}
       
   123 
    87 	CProviderProbe* sap = new (ELeave) CProviderProbe(this);
   124 	CProviderProbe* sap = new (ELeave) CProviderProbe(this);
    88 	sap->iNext = iList;
   125 	sap->iNext = iList;
    89 	iList = sap;
   126 	iList = sap;
    90 	return sap;
   127 	return sap;
    91 	}
   128 	}
    95 // *************************
   132 // *************************
    96 // Disconnect SAP from the protocol
   133 // Disconnect SAP from the protocol
    97 //
   134 //
    98 void CProtocolProbe::CancelSAP(const CServProviderBase* aSAP)
   135 void CProtocolProbe::CancelSAP(const CServProviderBase* aSAP)
    99 	{
   136 	{
       
   137 	
   100 	CProviderProbe **h, *sap;
   138 	CProviderProbe **h, *sap;
   101 	for (h = &iList; (sap = *h) != NULL; h = &sap->iNext)
   139 	for (h = &iList; (sap = *h) != NULL; h = &sap->iNext)
   102 		if (sap == aSAP)
   140 		if (sap == aSAP)
   103 			{
   141 			{
   104 			*h = sap->iNext;
   142 			*h = sap->iNext;
   105 			break;
   143 			break;
   106 			}
   144 			}
   107 	}
   145 	}
   108 
   146 
   109 
       
   110 // CProtocolProbe::NetworkAttachedL
   147 // CProtocolProbe::NetworkAttachedL
   111 // ********************************
   148 // ********************************
   112 // When network becomes available, do the hooking!
   149 // When network becomes available, do the hooking!
   113 //
   150 //
   114 void CProtocolProbe::NetworkAttachedL()
   151 void CProtocolProbe::NetworkAttachedL()
   115 	{
   152 	{
       
   153 
   116 	NetworkService()->BindL(this, MIp6Hook::BindPostHook());
   154 	NetworkService()->BindL(this, MIp6Hook::BindPostHook());
   117 	NetworkService()->BindL(this, MIp6Hook::BindPostHook()+1);
   155 	NetworkService()->BindL(this, MIp6Hook::BindPostHook()+1);
   118 	}
   156 
   119 
   157 	// initialise dump file
   120 //
   158 	if(iFileOpen)
   121 //	CProtocolProbe::Deliver
   159 		{
       
   160 		iFile.Close();
       
   161 		iFileOpen = EFalse;
       
   162 		}
       
   163 	if(iFileServerOpen)
       
   164 		{
       
   165 		iFs.Close();
       
   166 		iFileServerOpen = EFalse;
       
   167 		}
       
   168 
       
   169 	User::LeaveIfError(iFs.Connect());
       
   170     iFileServerOpen = ETrue;
       
   171     TBuf<50> filename;
       
   172     filename.Append(KLogFolder);
       
   173     filename.Append(KTcpDumpFolder);
       
   174     filename.Append(KProbeDumpFile);
       
   175 	User::LeaveIfError(iFile.Replace(iFs, filename, EFileWrite));
       
   176     iFileOpen = ETrue;
       
   177 
       
   178     // allocate buffer
       
   179     if(!iBufCreated)
       
   180         {
       
   181 		const TInt KMaxBufferSize = 65535;
       
   182         iBuf.CreateL(KMaxBufferSize);
       
   183         iBufCreated = ETrue;
       
   184         }
       
   185     
       
   186 	LibcapDumpFileHeader();
       
   187 	}
       
   188 
       
   189 void CProtocolProbe::Queue(RMBufChain &aPacket)
       
   190 //
       
   191 //  Takes a copy of aPacket, adds it to the queue and triggers the callback
       
   192 //
       
   193 	{
       
   194 
       
   195 	RMBufPacketBase copy;
       
   196 	TRAPD(err, copy.CopyPackedL(aPacket));
       
   197 	if (err == KErrNone)
       
   198 		{
       
   199 
       
   200 		//
       
   201 		// Calculate packet time-stamp
       
   202 		//
       
   203 		TTime newTime;
       
   204 		newTime.UniversalTime();
       
   205 		TTimeIntervalMicroSeconds interval = newTime.MicroSecondsFrom(iTimeOrigin);
       
   206 
       
   207 		const TInt KMicrosInASecond = 1000000;
       
   208 
       
   209 		//TUint32 micros = interval.Int64().Low();
       
   210 		TUint32 micros = I64LOW(interval.Int64());//.Low();  x.Low() -> I64LOW(x)
       
   211 		TUint32 secs = micros / KMicrosInASecond;
       
   212 		micros -= (secs * KMicrosInASecond);
       
   213 
       
   214 		//
       
   215 		// Reuse the protocol and flags fields of
       
   216 		// RMBufPktInfo to store the time-stamp
       
   217 		//
       
   218 		RMBufPktInfo* info = RMBufPacket::PeekInfoInChain(copy);
       
   219 		info->iProtocol = static_cast<TInt>(secs);
       
   220 		info->iFlags = static_cast<TUint>(micros);
       
   221 
       
   222 		iQueue.Append(copy);
       
   223 		iDumpCb.CallBack();
       
   224 		}
       
   225 	else
       
   226 		{
       
   227 		copy.Free();
       
   228 		}
       
   229 	}
       
   230 
       
   231 
       
   232 //
       
   233 //	CProtocolProbe::Dump
   122 //	***********************
   234 //	***********************
   123 //	Generate a copy of the packet to every bound provider
   235 //	Log the packet to file
   124 //
   236 //
   125 void CProtocolProbe::Deliver(RMBufChain &aPacket)
   237 void CProtocolProbe::Dump(RMBufChain &aPacket)
   126 	{
   238 	{
   127 	const RMBufPktInfo *const info = RMBufPacketBase::PeekInfoInChain(aPacket);
   239 
   128 
   240 	RMBufPacket packet;
   129 	for (CProviderProbe* sap = iList; sap != NULL; sap = sap->iNext)
   241 	packet.Assign(aPacket);
   130 		{
   242 	RMBufPktInfo* info = packet.Unpack();
   131 		if (sap->IsReceiving(*info))
   243 
   132 			{
   244 	TUint32 secs = static_cast<TUint32>(info->iProtocol);
   133 			RMBufPacketBase copy;
   245 	TUint32 micros = static_cast<TUint32>(info->iFlags);
   134 			TRAPD(err, copy.CopyPackedL(aPacket));
   246 
   135 			if (err == KErrNone)
   247     iBuf.SetMax();
   136 				sap->Process(copy, this);
   248     packet.CopyOut(iBuf, 0);
   137 			else
   249     if(iBuf.Length() != info->iLength)
   138 				copy.Free();
   250         {
   139 			}
   251         iBuf.SetLength(info->iLength);
   140 		}
   252         }
   141 	}
   253 	LibcapDump(iBuf, secs, micros);
   142 
   254 	packet.Free();
       
   255 	}
   143 
   256 
   144 TInt CProtocolProbe::Send(RMBufChain &aPacket, CProtocolBase* aSrc)
   257 TInt CProtocolProbe::Send(RMBufChain &aPacket, CProtocolBase* aSrc)
   145 	{
   258 	{
   146 	Deliver(aPacket);
   259 
       
   260 	Queue(aPacket);
   147 	return CProtocolPosthook::Send(aPacket, aSrc);
   261 	return CProtocolPosthook::Send(aPacket, aSrc);
   148 	}
   262 	}
   149 
   263 
   150 void CProtocolProbe::Process(RMBufChain &aPacket, CProtocolBase* aSrc)
   264 void CProtocolProbe::Process(RMBufChain &aPacket, CProtocolBase* aSrc)
   151 	{
   265 	{
   152 	Deliver(aPacket);
   266 
       
   267 	Queue(aPacket);
   153 	CProtocolPosthook::Process(aPacket, aSrc);
   268 	CProtocolPosthook::Process(aPacket, aSrc);
   154 	}
   269 	}
       
   270 
       
   271 void CProtocolProbe::LibcapDumpFileHeader()
       
   272 //
       
   273 //  Dump file header in a format compatible with Libcap
       
   274 //
       
   275 //  Format is:
       
   276 //  
       
   277 //  struct FileHeader
       
   278 //      {
       
   279 //	    TUint32 magic; 
       
   280 //	    TUint16 version_major;
       
   281 //	    TUint16 version_minor;
       
   282 //	    TUint32 thiszone;	/* gmt to local correction */
       
   283 //	    TUint32 sigfigs;	/* accuracy of timestamps */
       
   284 //	    TUint32 snaplen;	/* max length saved portion of each pkt */
       
   285 //	    TUint32 linktype;	/* data link type (LINKTYPE_*) */
       
   286 //      };
       
   287 //
       
   288 //  Note LINKTYPE specified in libpcap/bpf/net/bpf.h (see www.tcpdump.org)
       
   289 //
       
   290 	{
       
   291 
       
   292 	TBuf8<sizeof(TUint32)*5+sizeof(TUint16)*2> fileHeader;
       
   293 	*((TUint32*) &(fileHeader.Ptr()[0])) = 0xa1b2c3d4;
       
   294 	*((TUint16*) &(fileHeader.Ptr()[4])) = 0x02; 
       
   295 	*((TUint16*) &(fileHeader.Ptr()[6])) = 0x04; 
       
   296 	*((TUint32*) &(fileHeader.Ptr()[8])) = 0x00;
       
   297 	*((TUint32*) &(fileHeader.Ptr()[12])) = 0x00;
       
   298 	*((TUint32*) &(fileHeader.Ptr()[16])) = 0xffff;
       
   299 	*((TUint32*) &(fileHeader.Ptr()[20])) = 12;       // DLT_RAW		12	/* raw IP */
       
   300 	fileHeader.SetLength(fileHeader.MaxLength());
       
   301 
       
   302 	iFile.Write(fileHeader);
       
   303 	}
       
   304 
       
   305 void CProtocolProbe::LibcapDump(const TDesC8& aBuffer, TUint32 aTimeStampSecs, TUint32 aTimeStampMicros)
       
   306 //
       
   307 //  Dumps a packet in a format compatbible with Libcap
       
   308 //
       
   309 //  For each record the format is:
       
   310 //
       
   311 //  struct record 
       
   312 //      {
       
   313 //      TUint32 sec;	/* time stamp - secs*/
       
   314 //      TUint32 usec;	/* time stamp - microsecs*/
       
   315 //      TUint32 captureLen;	/* length packet captured */
       
   316 //      TUint32 packetLen;	/* total length of packet*/
       
   317 //      };
       
   318 //
       
   319 //  Byte ordering of the header is little endian
       
   320 //  Byte ordering of the packet is network byte order (big endian)
       
   321 //
       
   322 	{
       
   323 	
       
   324 	TBuf8<sizeof(TUint32)*4> recordHeader;
       
   325 	recordHeader.FillZ();
       
   326 
       
   327 	*((TUint32*) &(recordHeader.Ptr()[0])) = aTimeStampSecs;
       
   328 	*((TUint32*) &(recordHeader.Ptr()[4])) = aTimeStampMicros;
       
   329 	*((TUint32*) &(recordHeader.Ptr()[8])) = aBuffer.Length();
       
   330 	*((TUint32*) &(recordHeader.Ptr()[12])) = aBuffer.Length();
       
   331 	recordHeader.SetLength(recordHeader.MaxLength());
       
   332 
       
   333 	iFile.Write(recordHeader);
       
   334 	iFile.Write(aBuffer);
       
   335 	}
       
   336 
       
   337 
       
   338 
       
   339 TInt CProtocolProbe::DumpCb(TAny* aThisPtr)
       
   340 //
       
   341 //  Callback function - calls DumpQueuedPackets()
       
   342 //
       
   343 	{
       
   344 
       
   345 	CProtocolProbe* self = static_cast<CProtocolProbe*>(aThisPtr);
       
   346 	self->DumpQueuedPackets();
       
   347 	return KErrNone;
       
   348 	}
       
   349 
       
   350 void CProtocolProbe::DumpQueuedPackets()
       
   351 //
       
   352 //  Dumps all packets on the queue to the log file
       
   353 //
       
   354 	{
       
   355 
       
   356 	RMBufPacketBase packet;
       
   357 	while(iQueue.Remove(packet))
       
   358 		{
       
   359 		Dump(packet);
       
   360 		}
       
   361 	}