linklayerprotocols/ethernetnif/log/eth_log.cpp
changeset 0 af10295192d8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/linklayerprotocols/ethernetnif/log/eth_log.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,169 @@
+// Copyright (c) 2003-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:
+// Ethernet libcap format logging
+// 
+//
+
+/**
+ @file
+ @internalComponent 
+*/
+
+#include "eth_log.h"
+
+#ifdef TCPDUMP_LOGGING
+
+CEthLog::CEthLog() :
+	iUnixTimeBase(KUnixTimeBaseDes)
+{
+}
+
+CEthLog::~CEthLog()
+{
+	__FLOG_CLOSE; 
+}
+
+CEthLog* CEthLog::NewL()
+{
+	CEthLog* self = new (ELeave) CEthLog;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self
+	return self;
+}
+
+void CEthLog::ConstructL()
+{
+	iEthTcpDumpLogFileName = KEthTcpDump;
+	__FLOG_OPEN(KEthTcpDumpFirstTag,KEthTcpDump);
+}
+
+/**
+Dumps a packet in a pcap format (see www.ethereal.com)
+For each record the format is:
+struct timeval - time packet received
+number of octects in packet
+number of octects from packet in file - ie. the number that we captured.  For this purpose, this will be all of them.
+Byte ordering of the header is little endian
+Byte ordering of the packet is network byte order (big endian)
+@param aCaptureTime The time that the packet was captured
+@param RMBufChain& aBuffer Buffer to dump
+*/
+void CEthLog::DumpFrame(TTime aCaptureTime, RMBufChain& aPdu)
+{
+	TBuf8<16> recordHeader; // one TInt64 for time, one TUint32 for observed packet length, one TUint32 for captured packet length
+	recordHeader.SetLength(recordHeader.MaxLength());
+
+	TInt err;
+	// Build the header for this frame
+	TTimeIntervalSeconds captureTimeSecs;
+	
+	err = aCaptureTime.SecondsFrom(iUnixTimeBase, captureTimeSecs);
+	if(err)	// if there's an overflow, then stick all zeros in - not good, but at least we got the data
+		captureTimeSecs = 0;
+		
+	TInt captureTimeMicroSecs;
+	captureTimeMicroSecs = I64LOW(aCaptureTime.Int64());
+	captureTimeMicroSecs = captureTimeMicroSecs % 1000000; // get microseconds component
+	
+	recordHeader[0]= static_cast<TUint8>((captureTimeSecs.Int() & 0x000000ff));
+	recordHeader[1]= static_cast<TUint8>((captureTimeSecs.Int() & 0x0000ff00) >> 8);
+	recordHeader[2]= static_cast<TUint8>((captureTimeSecs.Int() & 0x00ff0000) >> 16);
+	recordHeader[3]= static_cast<TUint8>((captureTimeSecs.Int() & 0xff000000) >> 24);
+	recordHeader[4]= static_cast<TUint8>((captureTimeMicroSecs & 0x000000ff));
+	recordHeader[5]= static_cast<TUint8>((captureTimeMicroSecs & 0x0000ff00) >> 8);
+	recordHeader[6]= static_cast<TUint8>((captureTimeMicroSecs & 0x00ff0000) >> 16);
+	recordHeader[7]= static_cast<TUint8>((captureTimeMicroSecs & 0xff000000) >> 24);
+
+	TInt32 dataBytes = aPdu.Length();
+
+	recordHeader[8]= static_cast<TUint8>((dataBytes & 0x000000ff));	// first entry shows the length of the packet
+	recordHeader[9]= static_cast<TUint8>((dataBytes & 0x0000ff00) >> 8);
+	recordHeader[10]= static_cast<TUint8>((dataBytes & 0x00ff0000) >> 16);
+	recordHeader[11]= static_cast<TUint8>((dataBytes & 0xff000000) >> 24);
+
+	recordHeader[12]=recordHeader[8];	// second shows how much of it we've written to the file
+	recordHeader[13]=recordHeader[9];
+	recordHeader[14]=recordHeader[10];
+	recordHeader[15]=recordHeader[11];
+
+	// create a temporary buffer to hold the pdu (flogger needs a descriptor, so we have to un-mbuf the data)
+	// could put this on the heap, but start by trying it on the stack because we don't have to do memory allocations that way
+	// might be worth having a permanent ~1500 byte HBufC on the heap to reuse here
+	TBuf8<KDefaultMtuSetting + KEtherLLCHeaderSize> pdu;
+	pdu.SetMax();
+	aPdu.CopyOut(pdu);
+	
+	__FLOG_BINARY((recordHeader));
+	__FLOG_BINARY((pdu));
+}
+
+/**
+Dump file header to show that this is a pcap capture file in pcap format
+Format is (from winpcap savefile.c):
+hdr.magic = TCPDUMP_MAGIC;
+hdr.version_major = PCAP_VERSION_MAJOR;
+hdr.version_minor = PCAP_VERSION_MINOR;
+hdr.thiszone = thiszone;
+hdr.snaplen = snaplen;
+hdr.sigfigs = 0;
+hdr.linktype = linktype;
+@see http://www.ethereal.com/lists/ethereal-dev/199909/msg00124.html for more details
+*/
+void CEthLog::DumpTcpDumpFileHeader()
+{
+	const TUint headerSize = 24; // header is 24 bytes long
+
+	TBuf8<headerSize> fileHeader;
+	fileHeader.SetLength(fileHeader.MaxLength());
+
+	fileHeader[0] = 0xd4;	// first four bytes - pcap magic number, indicates this is a pcap format file
+	fileHeader[1] = 0xc3;
+	fileHeader[2] = 0xb2;
+	fileHeader[3] = 0xa1;
+
+	fileHeader[4] = 0x02;	// two bytes of major version number
+	fileHeader[5] = 0x00;
+
+	fileHeader[6] = 0x04;	// two bytes of minor version number
+	fileHeader[7] = 0x00;
+
+	// find the offset from UTC of this device
+	TLocale locale;
+	TInt32 offset = locale.UniversalTimeOffset().Int();
+
+	fileHeader[8] =	static_cast<TUint8>(((offset & 0xff000000) >> 24));		// four bytes of offset from UTC in seconds
+	fileHeader[9] = static_cast<TUint8>(((offset & 0x00ff0000) >> 16));
+	fileHeader[10] = static_cast<TUint8>(((offset & 0x0000ff00) >> 8));		
+	fileHeader[11] = static_cast<TUint8>((offset & 0x000000ff));
+
+	fileHeader[12] = 0x00;		// four bytes of timestamp accuracy (not sure of units) - just set to zero, no-one seems to use them
+	fileHeader[13] = 0x00;
+	fileHeader[14] = 0x00;		
+	fileHeader[15] = 0x00;
+
+	fileHeader[16] = 0xFF;		// four bytes of maximum snapshot length - we're just going set it to something big
+	fileHeader[17] = 0xFF;
+	fileHeader[18] = 0x00;		
+	fileHeader[19] = 0x00;
+
+	fileHeader[20] = 0x01;		// four bytes of packet capture type (0x01 for 10Mb ethernet (and other speeds, I suspect!))
+	fileHeader[21] = 0x00;
+	fileHeader[22] = 0x00;		
+	fileHeader[23] = 0x00;
+
+	__FLOG_BINARY((fileHeader));
+}
+
+#endif