networkprotocols/iphook/inhook6example/src/exadump.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // exadump.cpp - packet dump plugin example module
       
    15 // The packet dump implementation.
       
    16 //
       
    17 
       
    18 
       
    19 
       
    20 /**
       
    21  @file exadump.cpp
       
    22 */
       
    23 
       
    24 #include <f32file.h>
       
    25 
       
    26 #include "protocol_module.h"
       
    27 #include "exadump.h"
       
    28 
       
    29 
       
    30 //
       
    31 // The "glue" between the protocol implementation and the generic protocol family module.
       
    32 // (This section should not have any doxygen comments, because the ProtocolModule can be
       
    33 // implemented multiple times in different examples -- the comments would be lost).
       
    34 //
       
    35 TInt ProtocolModule::NumProtocols()
       
    36 	{
       
    37 	return 1;
       
    38 	}
       
    39 
       
    40 void ProtocolModule::Describe(TServerProtocolDesc &aDesc, const TInt /*aIndex*/)
       
    41 	{
       
    42 	CProtocolExadump::Describe(aDesc);
       
    43 	}
       
    44 
       
    45 CProtocolBase *ProtocolModule::NewProtocolL(TUint aSockType, TUint aProtocol)
       
    46 	{
       
    47 	(void)aSockType;
       
    48 	(void)aProtocol;
       
    49 	return new (ELeave) CProtocolExadump;
       
    50 	}
       
    51 
       
    52 //
       
    53 //
       
    54 // The real implementation
       
    55 //
       
    56 //
       
    57 
       
    58 void CProtocolExadump::Describe(TServerProtocolDesc &aDesc)
       
    59 	/**
       
    60 	* Fills in the TServerProtocolDesc.
       
    61 	*
       
    62 	* @retval aDesc	The description of the protocol.
       
    63 	*
       
    64 	* A class specific static function can be used, as the information is
       
    65 	* always the same. Some other impelmentations might have non-static
       
    66 	* version, if some fields of the TServerProtocolDesc are dynamic and
       
    67 	* depend on the object. The following are initialized:
       
    68 	*
       
    69 	* - iName		The name of the protocol ("exadump").
       
    70 	* - iAddrFamily	The address family of the protocol.
       
    71 	* - iProtocol	The protocol number.
       
    72 	*				The combination family + protocol number should
       
    73 	*				be unique.
       
    74 	* - iVersion	Mostly unused?
       
    75 	* - iByteOrder	Mostly unused?
       
    76 	* - iServiceInfo	Connectionless datagram sockets (only if SAP's)
       
    77 	* - iNamingServices	Support RHostResolver and like?
       
    78 	* - iSecurity	Mostly unused?
       
    79 	* - iMessageSize	??
       
    80 	* - iServiceTypeInfo	??
       
    81 	* - iNumSockets	Max number of SAP's.)
       
    82 	*
       
    83 	*/
       
    84 	{
       
    85 /** @code */
       
    86 	aDesc.iName =			_S("exadump");
       
    87 	aDesc.iAddrFamily =		0x101f6cfe; // Use UID as family value.
       
    88 	aDesc.iSockType =		KSockDatagram;
       
    89 	aDesc.iProtocol =		1000;
       
    90 	aDesc.iVersion =		TVersion(1, 0, 0);
       
    91 	aDesc.iByteOrder =		EBigEndian;
       
    92 	aDesc.iServiceInfo =	0;
       
    93 	aDesc.iNamingServices = 0;
       
    94 	aDesc.iSecurity =		0;
       
    95 	aDesc.iMessageSize =	0;
       
    96 	aDesc.iServiceTypeInfo = 0;
       
    97 	aDesc.iNumSockets =		0;
       
    98 /** @endcode */
       
    99 	}
       
   100 
       
   101 
       
   102 void CProtocolExadump::Identify(TServerProtocolDesc *aDesc) const
       
   103 	/**
       
   104 	* Returns the protocol description.
       
   105 	*
       
   106 	* The socket server and other protocols use this function to
       
   107 	* retrieve the basic information about the protocol.
       
   108 	*
       
   109 	* @retval	aDesc	The protocol description.
       
   110 	*/
       
   111 	{
       
   112 /** @code */
       
   113 	Describe(*aDesc);
       
   114 /** @endcode */
       
   115 	}
       
   116 
       
   117 
       
   118 CProtocolExadump::CProtocolExadump()
       
   119 	/** Constructor. */
       
   120 	{
       
   121 /** @code */
       
   122 	// Base time as expected by Unix systems. Note that
       
   123 	// day and month numbering starts from ZERO!
       
   124 	iBase.Set(_L("19700000:000000.000000"));
       
   125 /** @endcode */
       
   126 	}
       
   127 
       
   128 CProtocolExadump::~CProtocolExadump()
       
   129 	/**
       
   130 	* Destructor.
       
   131 	*
       
   132 	* Release allocated resources.
       
   133 	*/
       
   134 	{
       
   135 /** @code */
       
   136 	if (iOpen > 0)
       
   137 		{
       
   138 		iDumpFile.Close();
       
   139 		iFS.Close();
       
   140 		}
       
   141 	delete iBuffer;
       
   142 /** @endcode */
       
   143 	}
       
   144 
       
   145 //
       
   146 
       
   147 // CProtocolExadump::NetworkAttachedL
       
   148 // ********************************
       
   149 void CProtocolExadump::NetworkAttachedL()
       
   150 	/**
       
   151 	* When network becomes available, do the hooking.
       
   152 	*
       
   153 	*/
       
   154 	{
       
   155 /** @code */
       
   156 	// Install a hook to dump all accepted packets just
       
   157 	// before they are passed to the upper layer
       
   158 	// protocol. The calling order of this hook, relative
       
   159 	// to other hooks can be controlled through the tcpip.ini
       
   160 	// option in the [hook] section
       
   161 	//
       
   162 	// hook_inany= *,exadump
       
   163 	//
       
   164 	// (call after all others) or
       
   165 	//
       
   166 	// hook_inany= exadump
       
   167 	//
       
   168 	// (call before all others).
       
   169 	//
       
   170 	NetworkService()->BindL(this, MIp6Hook::BindHookAll());
       
   171 
       
   172 	// Install a hook to dump outbound packets. The calling
       
   173 	// order of this hook, relative to other hooks can be
       
   174 	// controlled through the tcpip.ini option in the [hook] section:
       
   175 	//
       
   176 	// hook_flow= *,exadump
       
   177 	//
       
   178 	// or even
       
   179 	//
       
   180 	// hook_flow= exadump,*,exadump
       
   181 	//
       
   182 	// which would give two dumps out of each packet. One before any other
       
   183 	// flow hooks, and another one after all of them.
       
   184 	//
       
   185 	NetworkService()->BindL(this, MIp6Hook::BindFlowHook());
       
   186 /** @endcode */
       
   187 	}
       
   188 
       
   189 
       
   190 //
       
   191 // MIp6Hook specifications
       
   192 
       
   193 MFlowHook *CProtocolExadump::OpenL(TPacketHead & /*aHead*/, CFlowContext * /*aFlow*/)
       
   194 	/**
       
   195 	* Decides whether to attach hook on flow or not.
       
   196 	*
       
   197 	* This example attaches every flow, but it does not require
       
   198 	* a separate context for each flow. Thus, the MFlowHook has been
       
   199 	* mixed into the CProtocolExadump class and it uses itself by
       
   200 	* simply returning this pointer.
       
   201 	*
       
   202 	* @return	'this' as MFlowHook (always non-NULL)
       
   203 	*/
       
   204 	{
       
   205 /** @code */
       
   206 	Open();			// Increment reference count!
       
   207 	return this;
       
   208 /** @endcode */
       
   209 	}
       
   210 
       
   211 TInt CProtocolExadump::ApplyL(RMBufHookPacket& aPacket, RMBufRecvInfo & aInfo)
       
   212 	/**
       
   213 	* Dumps the packet.
       
   214 	*
       
   215 	* This is called for each incoming packet. The return is always
       
   216 	* KIp6Hook_PASS, because this does not try to modify or otherwise
       
   217 	* change the normal packet processing.
       
   218 	*
       
   219 	* @param aPacket	The packet data
       
   220 	* @param aInfo		The packet information
       
   221 	*
       
   222 	* @return KIp6Hook_PASS
       
   223 	*/
       
   224 	{
       
   225 /** @code */
       
   226 	DoPacket(aPacket, aInfo);
       
   227 	return KIp6Hook_PASS;
       
   228 /** @endcode */
       
   229 	}
       
   230 
       
   231 
       
   232 //
       
   233 // MFlowHook methods, because MFlowHook is mixed in
       
   234 
       
   235 void CProtocolExadump::Open()
       
   236 	/**
       
   237 	* Routes MFlowHook::Open to CProtocolPosthook::Open
       
   238 	*/
       
   239 	{
       
   240 /** @code */
       
   241 	CProtocolPosthook::Open();
       
   242 /** @endcode */
       
   243 	}
       
   244 
       
   245 void CProtocolExadump::Close()
       
   246 	/**
       
   247 	* Routes MFlowHook::Close to CProtocolPosthook::Close
       
   248 	*/
       
   249 	{
       
   250 /** @code */
       
   251 	CProtocolPosthook::Close();
       
   252 /** @endcode */
       
   253 	}
       
   254 
       
   255 TInt CProtocolExadump::ReadyL(TPacketHead & /*aHead*/)
       
   256 	/**
       
   257 	* Tests if flow is ready.
       
   258 	*
       
   259 	* In this example there is nothing that would make the flow
       
   260 	* blocked, and always return KErrNone.
       
   261 	*
       
   262 	* @return KErrNone.
       
   263 	*/
       
   264 	{
       
   265 	return KErrNone;
       
   266 	}
       
   267 
       
   268 TInt CProtocolExadump::ApplyL(RMBufSendPacket &aPacket, RMBufSendInfo &aInfo)
       
   269 	/**
       
   270 	* Dumps the packet.
       
   271 	*
       
   272 	* This is called for each outgoing packet. The return is always
       
   273 	* KErrNone, because this does not try to modify or otherwise
       
   274 	* change the normal packet processing.
       
   275 	*
       
   276 	* @param aPacket	The packet data
       
   277 	* @param aInfo		The packet information
       
   278 	*
       
   279 	* @return KErrNone
       
   280 	*/
       
   281 	{
       
   282 /** @code */
       
   283 	DoPacket(aPacket, aInfo);
       
   284 	return KErrNone;
       
   285 /** @endcode */
       
   286 	}
       
   287 
       
   288 //
       
   289 // Own private functions
       
   290 
       
   291 /**
       
   292 * @name Some minimal definitions lifted from the PCAP headers.
       
   293 *
       
   294 * {@
       
   295 */
       
   296 #include <sys/time.h>
       
   297 #define PCAP_VERSION_MAJOR 2
       
   298 #define PCAP_VERSION_MINOR 4
       
   299 #define TCPDUMP_MAGIC 0xa1b2c3d4
       
   300 #define DLT_RAW		12	/* raw IP */
       
   301 
       
   302 struct pcap_file_header
       
   303 	/** PCAP dump file header */
       
   304 	{
       
   305 	TUint32 magic;
       
   306 	TUint16 version_major;
       
   307 	TUint16 version_minor;
       
   308 	TUint32 thiszone;	/* gmt to local correction */
       
   309 	TUint32 sigfigs;	/* accuracy of timestamps */
       
   310 	TUint32 snaplen;	/* max length saved portion of each pkt */
       
   311 	TUint32 linktype;	/* data link type (LINKTYPE_*) */
       
   312 	};
       
   313 
       
   314 struct pcap_pkthdr
       
   315 	/** PCAP dump file packet header */
       
   316 	{
       
   317 	struct timeval ts;	/* time stamp */
       
   318 	TUint32 caplen;		/* length of portion present */
       
   319 	TUint32 len;		/* length this packet (off wire) */
       
   320 	};
       
   321 /** @} */
       
   322 
       
   323 void CProtocolExadump::DoPacket(const RMBufPacketBase &aPacket, const RMBufPktInfo &aInfo)
       
   324 	/**
       
   325 	* Dump the packet.
       
   326 	*
       
   327 	* This is called for both incoming and outgoing packets, from the
       
   328 	* respective ApplyL methods.
       
   329 	*
       
   330 	* @param aPacket	The packet data
       
   331 	* @param aInfo		The packet inforrmation
       
   332 	*/
       
   333 	{
       
   334 /** @code */
       
   335 	// Open the dump file, if not already opened (or attempted).
       
   336 	if (iOpen == 0)
       
   337 		DoOpen(1500);
       
   338 	if (iOpen < 0)
       
   339 		return;	// cannot open output file.
       
   340 
       
   341 	//
       
   342 	// Build PCAP frame into iBuffer (pcap_pkthdr + snapped portion of the packet)
       
   343 	//
       
   344 	TPtr8 buf = iBuffer->Des();
       
   345 	struct pcap_pkthdr *const hdr = (struct pcap_pkthdr *)buf.Ptr();
       
   346 	TPtr8 ptr((TUint8 *)buf.Ptr() + sizeof(*hdr), buf.MaxLength() - sizeof(*hdr));
       
   347 
       
   348 	const TInt snap = aInfo.iLength > ptr.MaxLength() ? ptr.MaxLength() : aInfo.iLength;
       
   349 	ptr.SetLength(snap);
       
   350 	aPacket.CopyOut(ptr);
       
   351 
       
   352 	hdr->caplen = snap;
       
   353 	hdr->len = aInfo.iLength;
       
   354 
       
   355 	TTime stamp;
       
   356 	stamp.UniversalTime();
       
   357 	const TTimeIntervalMicroSeconds elapsed = stamp.MicroSecondsFrom(iBase);
       
   358 #ifdef I64INT
       
   359 	hdr->ts.tv_usec = I64INT(elapsed.Int64() % 1000000);
       
   360 	hdr->ts.tv_sec = I64INT(elapsed.Int64() / 1000000);
       
   361 #else
       
   362 	hdr->ts.tv_usec = (elapsed.Int64() % 1000000).GetTInt();
       
   363 	hdr->ts.tv_sec = (elapsed.Int64() / 1000000).GetTInt();
       
   364 #endif
       
   365 	//
       
   366 	// Write frame out.
       
   367 	//
       
   368 	iDumpFile.Write(buf, snap+sizeof(*hdr));
       
   369 /** @endcode */
       
   370 	}
       
   371 
       
   372 
       
   373 void CProtocolExadump::DoOpen(TInt aSnaplen)
       
   374 	/**
       
   375 	* Try opening the dump file.
       
   376 	*
       
   377 	* Opens the dump file and writes the file header to it.
       
   378 	*
       
   379 	* @param aSnaplen The snap length
       
   380 	*/
       
   381 	{
       
   382 /** @code */
       
   383 	// Just close the previous, if called with open file.
       
   384 	if (iOpen > 0)
       
   385 		{
       
   386 		iDumpFile.Close();
       
   387 		iFS.Close();
       
   388 		}
       
   389 
       
   390 	// Allocate a working buffer for the packet frames
       
   391 	// (include packet header and snaplen).
       
   392 	delete iBuffer;
       
   393 	iBuffer = HBufC8::NewMax(aSnaplen + sizeof(struct pcap_file_header));
       
   394 	if (iBuffer == NULL)
       
   395 		{
       
   396 		iOpen = KErrNoMemory;
       
   397 		return;
       
   398 		}
       
   399 
       
   400 	_LIT(KDumpFile, "exedump.dat");	// the name of the dump file.
       
   401 
       
   402 	iOpen = iFS.Connect();
       
   403 	if (iOpen != KErrNone)
       
   404 		return;
       
   405 	iOpen = iDumpFile.Replace(iFS, KDumpFile, EFileWrite);
       
   406 	if (iOpen != KErrNone)
       
   407 		{
       
   408 		iFS.Close();
       
   409 		return;
       
   410 		}
       
   411 
       
   412 	// Write the header
       
   413 	TPckgBuf<struct pcap_file_header> hdr;
       
   414 
       
   415 	hdr().magic = TCPDUMP_MAGIC;
       
   416 	hdr().version_major = PCAP_VERSION_MAJOR;
       
   417 	hdr().version_minor = PCAP_VERSION_MINOR;
       
   418 
       
   419 	hdr().thiszone = 0;
       
   420 	hdr().snaplen = aSnaplen;
       
   421 	hdr().sigfigs = 0;
       
   422 	hdr().linktype = DLT_RAW;
       
   423 	iDumpFile.Write(hdr, hdr.Length());
       
   424 	iOpen = 1;
       
   425 	return;
       
   426 /** @endcode */
       
   427 	}