networkprotocols/iphook/inhook6/include/in_pkt_platform.h
branchRCL_3
changeset 5 1422c6cd3f0c
child 10 c64cefac6e99
equal deleted inserted replaced
1:a579325b79dd 5:1422c6cd3f0c
       
     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 the License "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 // in_pkt.h - packet handling routines
       
    15 // Generic packet handling utility for mapping packet handling to the RMBufChain.
       
    16 //
       
    17 
       
    18 
       
    19 
       
    20 /**
       
    21  @file in_pkt_partner.h
       
    22  @publishedPartner
       
    23  @released
       
    24 */
       
    25 
       
    26 #ifndef __IN_PKTPARTNER_H__
       
    27 #define __IN_PKTPARTNER_H__
       
    28 
       
    29 #include <nifmbuf.h>
       
    30 
       
    31 //	RMBufPacketPeek
       
    32 //	***************
       
    33 class RMBufPacketPeek : public RMBufChain
       
    34 	/**
       
    35 	Extends RMBufChain to add functions to read packet data as a descriptor 
       
    36 	and as an IP header.
       
    37 
       
    38 	The RMBufChain is assumed to contain the raw packet, without
       
    39 	the info block prepended (e.g. if this class is used for RMBufPacketBase
       
    40 	derived handle, it must be in "unpacked" state).
       
    41 	
       
    42 	@since v7.0
       
    43 	@publishedAll
       
    44 	@released
       
    45 	*/
       
    46 	{
       
    47 public:
       
    48 	IMPORT_C TPtr8 Access(TInt aSize, TUint aOffset = 0);
       
    49 	IMPORT_C TIpHeader *GetIpHeader();
       
    50 	};
       
    51 
       
    52 //	TPacketHead
       
    53 //	***********
       
    54 class TPacketHead
       
    55 	/**
       
    56 	Storage for some precomputed information for an outbound packet flow.
       
    57 
       
    58 	The outbound TPacketHead is part of the flow context (CFlowContext).
       
    59 
       
    60 	The CFlowContext::Connect initializes the content from the parameters
       
    61 	of the flow (TFlowInfo) and runs the connection process.. The connection
       
    62 	process (MIp6Hook::OpenL and MFlowHook::ReadyL phases) completes the
       
    63 	information. After this, as long as the flow is connected, the content
       
    64 	is mostly frozen and <b>must not be modified by anyone</b>.
       
    65  
       
    66     When there is a need to change any flow information, the changes must
       
    67 	be done to the flow parameters (and not to TPacketHead). The change of
       
    68 	flow parameters also sets the CFlowContext::iChanged flag, and this
       
    69 	eventually causes a new CFlowContext::Connect, which re-initializes
       
    70 	the TPacketHead with the new information.
       
    71 
       
    72 	For each field in the TPacketHead, the hook writer must follow the
       
    73 	basic rule (only for fields that it intends to change):
       
    74 
       
    75 	- if some field is changed in MIp6Hook::OpenL, then the previous
       
    76 	value should be restored in the MFlowHook::ReadyL.
       
    77 	- an exeception: the hook must omit the restore, if the
       
    78 	previous value was unspecified value (for example, the source
       
    79 	address).
       
    80 	- the content of #iPacket (and #iOffset) are special: they cannot
       
    81 	be modified in the MIp6Hook::OpenL phase. A hook can
       
    82 	modify them only in the MFlowHook::ReadyL phase. And, if the hook
       
    83 	is adding an IP header for tunneling, it must save the current content
       
    84 	of these fields in the ReadyL function, and then clear out the fields
       
    85 	(it must make the iPacket empty and zero iOffset). The hook must add
       
    86 	the saved iPacket content below the added tunnel header in
       
    87 	MFlowHook::ApplyL .
       
    88 
       
    89 	@since v7.0
       
    90 	@publishedAll
       
    91 	@released
       
    92 	*/
       
    93 	{
       
    94 public:
       
    95 	IMPORT_C TBool ExtHdrGet(TInt aType, TInt& aOfs, TInt& aLen);
       
    96 	IMPORT_C TBool ExtHdrGetOrPrependL(TInt aType, TInt& aOfs, TInt& aLen);
       
    97 	IMPORT_C TBool ExtHdrGetOrAppendL(TInt aType, TInt& aOfs, TInt& aLen);
       
    98 	IMPORT_C void AddDestinationOptionL(const TPtrC8& aOption, TUint8 aAlign=0, TUint8 aModulo=4);
       
    99 	IMPORT_C void AddDestinationOptionL(const TUint8* aOption, TUint8 aLen, TUint8 aAlign=0, TUint8 aModulo=4);
       
   100 
       
   101 public:
       
   102 	/**
       
   103 	"Virtual" IP header. The IPv6 header stucture is used, but the same
       
   104 	format is <b>also</b> used for the IPv4 destinations (Version() == 4,
       
   105 	even though the header format is still IPv6!)
       
   106 	
       
   107 	This header is initialized in the beginning of the OpenL phase
       
   108 	as follows:
       
   109 	@li	Version = 0
       
   110 	@li	Traffic Class, copied from the flow iOptions.iTrafficClass
       
   111 	@li	Flow Label = 0
       
   112 	@li	Payload Length = 0 (dummy field, not used)
       
   113 	@li	Next Header, copied from the flow iProtocol
       
   114 	@li	Hop Limit, copied from the flow iOptions.iHopLimit
       
   115 	@li	Src Address, copied from the flow Local Address (usually unspecified)
       
   116 	@li	Dst Address, copied from the flow Remote Address
       
   117 	
       
   118 	At beginning of the ReadyL phase (= at end of OpenL), the destination
       
   119 	address (and iDstId) are used to find a route on the interface. Depending
       
   120 	on whether this address is IPv4 (mapped) or IPv6, the Version field is set
       
   121 	accordingly to either 4 or 6.
       
   122 
       
   123 	After succesfull completion of the ReadyL, this used for *each* packet
       
   124 	which needs an IP header to be generated on send. The Version() determines
       
   125 	whether IPv4 or IPv6 frame is to be generated (this is the initial
       
   126 	header in the packet, *before* running outbound ApplyL hooks):
       
   127 	
       
   128 	@verbatim
       
   129 	                   IPv6            IPv4
       
   130 	   Version         == 6            ==4
       
   131 	   Traffic Class   used as is      used as TOS
       
   132 	   Flow Label      used as is      ignored
       
   133 	   Payload Length  ignored         ignored
       
   134 	   Next Header     used as is      used as Protocol
       
   135 	   Hop Limit       used as is      used as TTL
       
   136 	   Src Address     used as is      used as IPv4 mapped
       
   137 	   Dst Address     used as is      used as IPv4 mapped
       
   138 	@endverbatim
       
   139 	*/
       
   140 	TInet6HeaderIP ip6;
       
   141 	/**
       
   142 	Contains the scope id associated with the destination address
       
   143 	which is stored in #ip6 Dst Address. This id and address must
       
   144 	always be considered as a unit. Logically, any change changes
       
   145 	both values.
       
   146 
       
   147 	iDstId is initialized from the flow context TFlowInfo::iRemote.Scope() at
       
   148 	beginning of the flow connect phase. If application does not define
       
   149 	this scope id, then the system will attempt to choose a default value
       
   150 	at beginning of the connect phase. If the default cannot be determined,
       
   151 	the flow is put into pending state (and no connect happens).
       
   152 
       
   153 	@par MIp6Hook::OpenL
       
   154 	On entry to the OpenL, the iDstId is always non-zero and destination
       
   155 	address is specified. If a hook changes the destination address in
       
   156 	OpenL method, it must provide the correct id value
       
   157 	which goes with the new destination. If it cannot do this, it
       
   158 	must either abort the connect by leaving with an error state, or it
       
   159 	can leave with PENDING (> 0) status to signal there is no route
       
   160 	for the new destination.
       
   161 	If the stack cannot find suitable interface for the destination, then
       
   162 	it aborts the connect phase, and the flow is placed into holding state.
       
   163 
       
   164 	@note
       
   165 		Only a tunneling hook can safely change the destination
       
   166 		address (a use of routing header can also be a kind of
       
   167 		tunneling).
       
   168 	
       
   169 	@par MFlowHook::ReadyL
       
   170 	If the hook changed the destination address (or id) in the OpenL,
       
   171 	the ReadyL must restore the original values back.
       
   172 
       
   173 	*/
       
   174 	TUint32 iDstId;
       
   175 	/**
       
   176 	Contains the scope id associated with the source address
       
   177 	which is stored in #ip6 Src address. This is defined when the source
       
   178 	address is defined, and otherwise undefined.
       
   179 
       
   180 	iSrcId is initialized from TFlowInfo::iLocal.Scope() at beginning of the
       
   181 	flow connect phase. If application defines the source address,
       
   182 	but does not specify this scope id, then the system chooses
       
   183 	the id based on the interface defined by the source address.
       
   184 	If scope and address are both specified, they must match the
       
   185 	selected interface.
       
   186 
       
   187 	@par MIp6Hook::OpenL
       
   188 	On entry to the OpenL, the iSrcId (and source address) may be
       
   189 	undefined (#iSourceSet = 0). If defined (iSourceSet = 1), then
       
   190 	both address and iSrcId are defined (iSrcId != 0). A hook may
       
   191 	force a reselection of the source just by zeroing the
       
   192 	iSourceSet.
       
   193 
       
   194 	@par MFlowHook::ReadyL
       
   195 	If the hook changed the source address (or id) in the OpenL,
       
   196 	the ReadyL must restore the original values back, but only
       
   197 	if the original value was defined (#iSourceSet = 1 in OpenL).
       
   198 	*/
       
   199 	TUint32 iSrcId;
       
   200 	/**
       
   201 	The source address has been set.
       
   202 
       
   203 	This bit indicates whether the value stored in #ip6 src field
       
   204 	and #iSrcId is to be used as a source address as is.
       
   205 
       
   206 	Initialized from TFlowInfo::iLocalSet, which tells whether user
       
   207 	specified tbe source address or not (e.g used RSocket Bind method).
       
   208 	The stack checks the value after each MIp6Hook::OpenL call, and
       
   209 	if the flag is set, the source in ip6 is used as is. If the flag
       
   210 	is zero, then the stack performs the normal source address selection
       
   211 	based on the current destination address (#iSrcId and destination
       
   212 	address).
       
   213 
       
   214 	@par MIp6Hook::OpenL
       
   215 	On entry, this flag is always set and source address is defined.
       
   216 	A hook may clear this flag, if it wants the
       
   217 	stack choose the source address based on current destination.
       
   218 	The clearing operation is normally needed only by a tunneling
       
   219 	hook.
       
   220 
       
   221 	@note
       
   222 		If the hook specifies the source address, it must be either
       
   223 		a valid source address for the interface or unspecified
       
   224 		address.
       
   225 
       
   226 	@par MFlowHook::ReadyL
       
   227 	Upon entry to the ReadyL, the source address is always fully
       
   228 	known (the hook can assume that #iSrcId and the #ip6 source
       
   229 	addresses are valid).
       
   230 	If the source address was set before the OpenL, then this
       
   231 	must restore the original value (along with the #iSrcId
       
   232 	and source address).
       
   233 	*/
       
   234 	TUint iSourceSet:1;
       
   235 #ifdef TPACKETHEAD_FRAGMENT
       
   236 	/**
       
   237 	The fragment processing alredy done.
       
   238 	
       
   239 	This bit is meaningful only in OpenL phase. If already set,
       
   240 	then some ealier hook has requested that the packet must
       
   241 	be fragmented to fit the mtu.
       
   242 	
       
   243 	A tunneling hook can set this bit in OpenL, if it needs
       
   244 	the fragmenting to happen before the ApplyL is called (e.g.
       
   245 	the fragments are tunneled instead of fragmenting the
       
   246 	tunneling).
       
   247 	
       
   248 	This bit can only be set or left as is. It cannot be cleared
       
   249 	once set.
       
   250 	*/
       
   251 	TUint iFragment:1;
       
   252 #endif
       
   253 	/**
       
   254 	Selector info, the upper layer protocol.
       
   255 
       
   256 	iProtocol has the same value as ip6.NextHeader() when iPacket is empty,
       
   257 	and otherwise it is the same as NextHeader() of the last extension
       
   258 	header in the iPacket.
       
   259 
       
   260 	The values of the other selector fields: #iIcmpType, #iIcmpCode
       
   261 	#iSrcPort and #iDstPort depend on iProtocol. Whenever iProtocol
       
   262 	is changed, the other fields must be updated accordingly.
       
   263 
       
   264 	@par MIp6Hook::OpenL
       
   265 	Because iPacket cannot be modified during the OpenL phase, the
       
   266 	content of this field and the Next Header (protocol) field in
       
   267 	the #ip6 pseudoheader must always be the same. This field should
       
   268 	be considered as <b>read-only</b>, unless the hook intends to
       
   269 	apply IP-in-IP tunneling, in which case the hook <b>must</b>
       
   270 	change the value to the appropriate tunneling protocol
       
   271 	(#KProtocolInet6Ipip or #KProtocolInetIpip).
       
   272 
       
   273     @par MFlowHook::ReadyL
       
   274 	Only a tunneling hook needs to restore the value here to match
       
   275 	the original upper layer protocol. See #iPacket for
       
   276 	more detailed information.
       
   277 	*/
       
   278 	TUint8 iProtocol;
       
   279 	/**
       
   280 	Selector field whose value depends on #iProtocol. 
       
   281  
       
   282 	If this field does not have meaning with the protocol,
       
   283 	the field content should be set to ZERO.
       
   284 	*/
       
   285 	TUint8 iIcmpType;
       
   286 	/**
       
   287 	Selector field whose value depends on #iProtocol. 
       
   288  
       
   289 	If this field does not have meaning with the protocol,
       
   290 	the field content should be set to ZERO.
       
   291 	*/
       
   292 	TUint8 iIcmpCode;
       
   293 	/**
       
   294 	Selector field whose value depends on #iProtocol. 
       
   295  
       
   296 	If this field does not have meaning with the protocol,
       
   297 	the field content should be set to ZERO.
       
   298 	*/
       
   299 	TUint16 iSrcPort;
       
   300 	/**
       
   301 	Selector field whose value depends on #iProtocol. 
       
   302  
       
   303 	If this field does not have meaning with the protocol,
       
   304 	the field content should be set to ZERO.
       
   305 	*/
       
   306 	TUint16 iDstPort;
       
   307 	/**
       
   308 	The amount of pre-computed IPv6 extension headers in iPacket which
       
   309 	are copied to the beginning of each outgoing packet
       
   310 
       
   311 	If iOffset > 0, then #iPacket includes that much of extension
       
   312 	headers that are copied in front of each packet.
       
   313 	*/
       
   314 	TInt iOffset;
       
   315 	/**
       
   316 	Pre-computed extension headers for all packets in this flow.
       
   317 	
       
   318 	These can only be added in the ReadyL phase. If any of the
       
   319 	ReadyL's adds extension headers into this, it must take care
       
   320 	of maintaining the correct Next Header in the virtual IP header
       
   321 	(and the original upper layer protocol must be placed in the
       
   322 	next header of the last extension header added.
       
   323 	
       
   324 	Stack copies the content of this to each outgoing packet, just below
       
   325 	the IP header, before running the ApplyL functions of the outbound
       
   326 	flow hooks.
       
   327 
       
   328 	@par MIp6Hook::OpenL
       
   329 	The iPacket <b>must not</b> be modified during the OpenL phase.
       
   330 
       
   331 	@par MFlowHook::ReadyL
       
   332 	A non-tunneling hook may add extension headers into the current
       
   333 	iPacket. A tunneling hook has more complex requirements:
       
   334 	it must save the current iPacket and #iOffset and initialize
       
   335 	iOffset = 0, and iPacket as empty.
       
   336 
       
   337     @par MFlowHook::ApplyL
       
   338 	When a tunneling hook adds the tunneling IP header, it
       
   339 	must also copy the saved iPacket below the added IP header.
       
   340 	*/
       
   341 	RMBufPacketPeek iPacket;
       
   342 	/**
       
   343 	The received packet which caused an ICMP error reply to be sent.
       
   344 
       
   345 	This is only used for ICMP error repply flows, and should be
       
   346 	ignored by others -- mainly for IPSEC hook. The packet, if
       
   347 	present, is in unpacked state.
       
   348 	*/
       
   349 	RMBufPacketBase iIcmp;
       
   350 	/**
       
   351 	The current destination interface.
       
   352 
       
   353  	This is ONLY used during connect/OpenL phase.
       
   354 
       
   355 	The value is maintained by the stack, and is intended as
       
   356 	read-only information for the hooks that have a use for
       
   357 	it (for example, IPSEC implementing VPN specific policies).
       
   358 
       
   359 	A hook must not modify this value (the stack will recompute
       
   360 	the value after each OpenL, based on the possibly changed
       
   361 	address parameters in the TPacketHead)
       
   362 
       
   363 	@par MIp6Hook::OpenL
       
   364 	<b>read-only</b>
       
   365 	@par MFlowHook::ReadyL
       
   366 	<b>read-only</b>
       
   367 	*/
       
   368  	TUint32 iInterfaceIndex;
       
   369 	};
       
   370 	
       
   371 //	TPacketPoker
       
   372 //	************
       
   373 class TPacketPoker
       
   374 	/**
       
   375 	Provides a utility for linear scanning of a chain of RMBuf objects (an RMBufChain).
       
   376 
       
   377 	An object of this type maintains a current point in the RMBufChain. This point 
       
   378 	can only move forward, and a leave occurs if the point advances beyond the 
       
   379 	end of the chain.
       
   380 
       
   381 	Any pointers and aligns arranged before the current point, remain valid: for 
       
   382 	example, you can save a reference and advance the pointer, and the reference 
       
   383 	remains usable.
       
   384  
       
   385 	If instead you need to go to a single specified offset, then use
       
   386 	RMBufChain::Goto() or RMBufPacketPeek::Access().
       
   387 
       
   388 	@post
       
   389 	A Generic implementation assert: 
       
   390 	after construct, iTail == 0 iff iCurrent == 0 (all scanned), or
       
   391 	in other words: as long as there are bytes after current point,
       
   392 	iTail will be non-zero (and More() returns ETrue).
       
   393 	All methods maintain this invariant or leave, if impossible.
       
   394 
       
   395 	Some other utility methods, not directly related to scanning, are also included. 
       
   396 	@since v7.0
       
   397 	@publishedAll
       
   398 	@released
       
   399 	*/
       
   400 	{
       
   401 public:
       
   402 	IMPORT_C TPacketPoker(RMBufChain &aChain);
       
   403 
       
   404 	inline void SkipL(TInt aSize)
       
   405 		/**
       
   406 		Moves the current point forward a specified number of bytes.
       
   407 
       
   408 		@param aSize Number of bytes to move forward
       
   409 		@leave KErrEof
       
   410 			if the request cannot be satisfied.
       
   411 		*/
       
   412 		{ if (aSize < iTail) { iTail -= aSize; iOffset += aSize; } else OverL(aSize); }
       
   413 
       
   414 	inline TUint8 *Ptr() const
       
   415 		/**
       
   416 		Raw pointer to the current point (can be invalid, if iTail = 0).
       
   417 	
       
   418 		@note Internal "unsafe" method
       
   419 		*/
       
   420 		{return iCurrent->Ptr() + iOffset; }
       
   421 
       
   422 	inline TUint8 *ReferenceL(TInt aSize = 1)
       
   423 		/**
       
   424 		Gets a pointer to the current point, such that
       
   425 		at least the specified minimum number of bytes can be read.
       
   426 
       
   427 		@param aSize
       
   428 			Specified minimum number of bytes to be read through
       
   429 			the returned pointer.
       
   430 		@return Raw data pointer
       
   431 		@leave KErrEof
       
   432 			if the request cannot be satisfied.
       
   433 		*/
       
   434 		{ if (iTail >= aSize) return Ptr(); else return AdjustL(aSize); }
       
   435 
       
   436 	inline TUint8 *ReferenceAndSkipL(TInt aSize)
       
   437 		/**
       
   438 		Gets a pointer to the current point, such that at least the
       
   439 		specified minimum number of bytes can be read,
       
   440 		and moves the point the specified number of bytes forward.
       
   441 
       
   442 		@param aSize
       
   443 			Specified minimum number of bytes to be read through the returned 
       
   444 			pointer, and the number of bytes to move forward
       
   445 		@return
       
   446 			Raw data pointer
       
   447 		@leave KErrEof
       
   448 			if the request cannot be satisfied.
       
   449 		*/
       
   450 		{ TUint8 *x = ReferenceL(aSize); SkipL(aSize); return x; }
       
   451 
       
   452 	inline TInt Remainder() const
       
   453 		/**
       
   454 		Gets the length of the contiguous space after the current point.	
       
   455 
       
   456 		@return Length after the current point
       
   457 		*/
       
   458 		{ return iTail; }
       
   459 
       
   460 	inline TBool AtBegin() const
       
   461 		/**
       
   462 		Tests whether the current point is at the beginning of an RMBuf.
       
   463 
       
   464 		@return ETrue if current point is at the beginning
       
   465 		*/
       
   466 		{ return iOffset == 0; }
       
   467 
       
   468 	inline TBool More() const
       
   469 		/**
       
   470 		Tests whether there is more data to scan.
       
   471 
       
   472 		@return ETrue if there is more data to scan
       
   473 		*/
       
   474 		{ return iTail > 0; }
       
   475 
       
   476 	IMPORT_C static TBool IsExtensionHeader(TInt aProtocolId);
       
   477 private:
       
   478 	IMPORT_C void OverL(TInt aSize);
       
   479 	IMPORT_C TUint8 *AdjustL(TInt aSize);
       
   480 	/** The RMBuf of the current point. */
       
   481 	RMBuf *iCurrent;
       
   482 	/** The offset of the current point in the RMBuf. */
       
   483 	TInt iOffset;
       
   484 	/** Remaining bytes starting from the current point in the RMBuf. */
       
   485 	TInt iTail;
       
   486 	};
       
   487 
       
   488 #endif