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