networkprotocols/iphook/inhook6/include/in_pkt.h
branchRCL_3
changeset 5 1422c6cd3f0c
parent 0 af10295192d8
equal deleted inserted replaced
1:a579325b79dd 5:1422c6cd3f0c
    24 */
    24 */
    25 
    25 
    26 #ifndef __IN_PKT_H__
    26 #ifndef __IN_PKT_H__
    27 #define __IN_PKT_H__
    27 #define __IN_PKT_H__
    28 
    28 
    29 #include <nifmbuf.h>
       
    30 #include "ip6_hdr.h"	// ..should eventually be <inet/ip6_hdr.h>? -- msa
    29 #include "ip6_hdr.h"	// ..should eventually be <inet/ip6_hdr.h>? -- msa
    31 #include "ip4_hdr.h"
    30 #include "ip4_hdr.h"
       
    31 class RMBufChain;
       
    32 
    32 
    33 
    33 #define TPACKETHEAD_FRAGMENT	1	//< Enable iFragment in TPacketHead
    34 #define TPACKETHEAD_FRAGMENT	1	//< Enable iFragment in TPacketHead
    34 
    35 
    35 /**
    36 /**
    36  TScopeType is only provided so that "magic" constants can be
    37  TScopeType is only provided so that "magic" constants can be
   100 		TInet6HeaderIP ip6;
   101 		TInet6HeaderIP ip6;
   101 		};
   102 		};
   102 	};
   103 	};
   103 
   104 
   104 
   105 
   105 //	RMBufPacketPeek
       
   106 //	***************
       
   107 class RMBufPacketPeek : public RMBufChain
       
   108 	/**
       
   109 	Extends RMBufChain to add functions to read packet data as a descriptor 
       
   110 	and as an IP header.
       
   111 
       
   112 	The RMBufChain is assumed to contain the raw packet, without
       
   113 	the info block prepended (e.g. if this class is used for RMBufPacketBase
       
   114 	derived handle, it must be in "unpacked" state).
       
   115 	
       
   116 	@since v7.0
       
   117 	@publishedAll
       
   118 	@released
       
   119 	*/
       
   120 	{
       
   121 public:
       
   122 	IMPORT_C TPtr8 Access(TInt aSize, TUint aOffset = 0);
       
   123 	IMPORT_C TIpHeader *GetIpHeader();
       
   124 	};
       
   125 
       
   126 //	TPacketHead
       
   127 //	***********
       
   128 class TPacketHead
       
   129 	/**
       
   130 	Storage for some precomputed information for an outbound packet flow.
       
   131 
       
   132 	The outbound TPacketHead is part of the flow context (CFlowContext).
       
   133 
       
   134 	The CFlowContext::Connect initializes the content from the parameters
       
   135 	of the flow (TFlowInfo) and runs the connection process.. The connection
       
   136 	process (MIp6Hook::OpenL and MFlowHook::ReadyL phases) completes the
       
   137 	information. After this, as long as the flow is connected, the content
       
   138 	is mostly frozen and <b>must not be modified by anyone</b>.
       
   139  
       
   140     When there is a need to change any flow information, the changes must
       
   141 	be done to the flow parameters (and not to TPacketHead). The change of
       
   142 	flow parameters also sets the CFlowContext::iChanged flag, and this
       
   143 	eventually causes a new CFlowContext::Connect, which re-initializes
       
   144 	the TPacketHead with the new information.
       
   145 
       
   146 	For each field in the TPacketHead, the hook writer must follow the
       
   147 	basic rule (only for fields that it intends to change):
       
   148 
       
   149 	- if some field is changed in MIp6Hook::OpenL, then the previous
       
   150 	value should be restored in the MFlowHook::ReadyL.
       
   151 	- an exeception: the hook must omit the restore, if the
       
   152 	previous value was unspecified value (for example, the source
       
   153 	address).
       
   154 	- the content of #iPacket (and #iOffset) are special: they cannot
       
   155 	be modified in the MIp6Hook::OpenL phase. A hook can
       
   156 	modify them only in the MFlowHook::ReadyL phase. And, if the hook
       
   157 	is adding an IP header for tunneling, it must save the current content
       
   158 	of these fields in the ReadyL function, and then clear out the fields
       
   159 	(it must make the iPacket empty and zero iOffset). The hook must add
       
   160 	the saved iPacket content below the added tunnel header in
       
   161 	MFlowHook::ApplyL .
       
   162 
       
   163 	@since v7.0
       
   164 	@publishedAll
       
   165 	@released
       
   166 	*/
       
   167 	{
       
   168 public:
       
   169 	IMPORT_C TBool ExtHdrGet(TInt aType, TInt& aOfs, TInt& aLen);
       
   170 	IMPORT_C TBool ExtHdrGetOrPrependL(TInt aType, TInt& aOfs, TInt& aLen);
       
   171 	IMPORT_C TBool ExtHdrGetOrAppendL(TInt aType, TInt& aOfs, TInt& aLen);
       
   172 	IMPORT_C void AddDestinationOptionL(const TPtrC8& aOption, TUint8 aAlign=0, TUint8 aModulo=4);
       
   173 	IMPORT_C void AddDestinationOptionL(const TUint8* aOption, TUint8 aLen, TUint8 aAlign=0, TUint8 aModulo=4);
       
   174 
       
   175 public:
       
   176 	/**
       
   177 	"Virtual" IP header. The IPv6 header stucture is used, but the same
       
   178 	format is <b>also</b> used for the IPv4 destinations (Version() == 4,
       
   179 	even though the header format is still IPv6!)
       
   180 	
       
   181 	This header is initialized in the beginning of the OpenL phase
       
   182 	as follows:
       
   183 	@li	Version = 0
       
   184 	@li	Traffic Class, copied from the flow iOptions.iTrafficClass
       
   185 	@li	Flow Label = 0
       
   186 	@li	Payload Length = 0 (dummy field, not used)
       
   187 	@li	Next Header, copied from the flow iProtocol
       
   188 	@li	Hop Limit, copied from the flow iOptions.iHopLimit
       
   189 	@li	Src Address, copied from the flow Local Address (usually unspecified)
       
   190 	@li	Dst Address, copied from the flow Remote Address
       
   191 	
       
   192 	At beginning of the ReadyL phase (= at end of OpenL), the destination
       
   193 	address (and iDstId) are used to find a route on the interface. Depending
       
   194 	on whether this address is IPv4 (mapped) or IPv6, the Version field is set
       
   195 	accordingly to either 4 or 6.
       
   196 
       
   197 	After succesfull completion of the ReadyL, this used for *each* packet
       
   198 	which needs an IP header to be generated on send. The Version() determines
       
   199 	whether IPv4 or IPv6 frame is to be generated (this is the initial
       
   200 	header in the packet, *before* running outbound ApplyL hooks):
       
   201 	
       
   202 	@verbatim
       
   203 	                   IPv6            IPv4
       
   204 	   Version         == 6            ==4
       
   205 	   Traffic Class   used as is      used as TOS
       
   206 	   Flow Label      used as is      ignored
       
   207 	   Payload Length  ignored         ignored
       
   208 	   Next Header     used as is      used as Protocol
       
   209 	   Hop Limit       used as is      used as TTL
       
   210 	   Src Address     used as is      used as IPv4 mapped
       
   211 	   Dst Address     used as is      used as IPv4 mapped
       
   212 	@endverbatim
       
   213 	*/
       
   214 	TInet6HeaderIP ip6;
       
   215 	/**
       
   216 	Contains the scope id associated with the destination address
       
   217 	which is stored in #ip6 Dst Address. This id and address must
       
   218 	always be considered as a unit. Logically, any change changes
       
   219 	both values.
       
   220 
       
   221 	iDstId is initialized from the flow context TFlowInfo::iRemote.Scope() at
       
   222 	beginning of the flow connect phase. If application does not define
       
   223 	this scope id, then the system will attempt to choose a default value
       
   224 	at beginning of the connect phase. If the default cannot be determined,
       
   225 	the flow is put into pending state (and no connect happens).
       
   226 
       
   227 	@par MIp6Hook::OpenL
       
   228 	On entry to the OpenL, the iDstId is always non-zero and destination
       
   229 	address is specified. If a hook changes the destination address in
       
   230 	OpenL method, it must provide the correct id value
       
   231 	which goes with the new destination. If it cannot do this, it
       
   232 	must either abort the connect by leaving with an error state, or it
       
   233 	can leave with PENDING (> 0) status to signal there is no route
       
   234 	for the new destination.
       
   235 	If the stack cannot find suitable interface for the destination, then
       
   236 	it aborts the connect phase, and the flow is placed into holding state.
       
   237 
       
   238 	@note
       
   239 		Only a tunneling hook can safely change the destination
       
   240 		address (a use of routing header can also be a kind of
       
   241 		tunneling).
       
   242 	
       
   243 	@par MFlowHook::ReadyL
       
   244 	If the hook changed the destination address (or id) in the OpenL,
       
   245 	the ReadyL must restore the original values back.
       
   246 
       
   247 	*/
       
   248 	TUint32 iDstId;
       
   249 	/**
       
   250 	Contains the scope id associated with the source address
       
   251 	which is stored in #ip6 Src address. This is defined when the source
       
   252 	address is defined, and otherwise undefined.
       
   253 
       
   254 	iSrcId is initialized from TFlowInfo::iLocal.Scope() at beginning of the
       
   255 	flow connect phase. If application defines the source address,
       
   256 	but does not specify this scope id, then the system chooses
       
   257 	the id based on the interface defined by the source address.
       
   258 	If scope and address are both specified, they must match the
       
   259 	selected interface.
       
   260 
       
   261 	@par MIp6Hook::OpenL
       
   262 	On entry to the OpenL, the iSrcId (and source address) may be
       
   263 	undefined (#iSourceSet = 0). If defined (iSourceSet = 1), then
       
   264 	both address and iSrcId are defined (iSrcId != 0). A hook may
       
   265 	force a reselection of the source just by zeroing the
       
   266 	iSourceSet.
       
   267 
       
   268 	@par MFlowHook::ReadyL
       
   269 	If the hook changed the source address (or id) in the OpenL,
       
   270 	the ReadyL must restore the original values back, but only
       
   271 	if the original value was defined (#iSourceSet = 1 in OpenL).
       
   272 	*/
       
   273 	TUint32 iSrcId;
       
   274 	/**
       
   275 	The source address has been set.
       
   276 
       
   277 	This bit indicates whether the value stored in #ip6 src field
       
   278 	and #iSrcId is to be used as a source address as is.
       
   279 
       
   280 	Initialized from TFlowInfo::iLocalSet, which tells whether user
       
   281 	specified tbe source address or not (e.g used RSocket Bind method).
       
   282 	The stack checks the value after each MIp6Hook::OpenL call, and
       
   283 	if the flag is set, the source in ip6 is used as is. If the flag
       
   284 	is zero, then the stack performs the normal source address selection
       
   285 	based on the current destination address (#iSrcId and destination
       
   286 	address).
       
   287 
       
   288 	@par MIp6Hook::OpenL
       
   289 	On entry, this flag is always set and source address is defined.
       
   290 	A hook may clear this flag, if it wants the
       
   291 	stack choose the source address based on current destination.
       
   292 	The clearing operation is normally needed only by a tunneling
       
   293 	hook.
       
   294 
       
   295 	@note
       
   296 		If the hook specifies the source address, it must be either
       
   297 		a valid source address for the interface or unspecified
       
   298 		address.
       
   299 
       
   300 	@par MFlowHook::ReadyL
       
   301 	Upon entry to the ReadyL, the source address is always fully
       
   302 	known (the hook can assume that #iSrcId and the #ip6 source
       
   303 	addresses are valid).
       
   304 	If the source address was set before the OpenL, then this
       
   305 	must restore the original value (along with the #iSrcId
       
   306 	and source address).
       
   307 	*/
       
   308 	TUint iSourceSet:1;
       
   309 #ifdef TPACKETHEAD_FRAGMENT
       
   310 	/**
       
   311 	The fragment processing alredy done.
       
   312 	
       
   313 	This bit is meaningful only in OpenL phase. If already set,
       
   314 	then some ealier hook has requested that the packet must
       
   315 	be fragmented to fit the mtu.
       
   316 	
       
   317 	A tunneling hook can set this bit in OpenL, if it needs
       
   318 	the fragmenting to happen before the ApplyL is called (e.g.
       
   319 	the fragments are tunneled instead of fragmenting the
       
   320 	tunneling).
       
   321 	
       
   322 	This bit can only be set or left as is. It cannot be cleared
       
   323 	once set.
       
   324 	*/
       
   325 	TUint iFragment:1;
       
   326 #endif
       
   327 	/**
       
   328 	Selector info, the upper layer protocol.
       
   329 
       
   330 	iProtocol has the same value as ip6.NextHeader() when iPacket is empty,
       
   331 	and otherwise it is the same as NextHeader() of the last extension
       
   332 	header in the iPacket.
       
   333 
       
   334 	The values of the other selector fields: #iIcmpType, #iIcmpCode
       
   335 	#iSrcPort and #iDstPort depend on iProtocol. Whenever iProtocol
       
   336 	is changed, the other fields must be updated accordingly.
       
   337 
       
   338 	@par MIp6Hook::OpenL
       
   339 	Because iPacket cannot be modified during the OpenL phase, the
       
   340 	content of this field and the Next Header (protocol) field in
       
   341 	the #ip6 pseudoheader must always be the same. This field should
       
   342 	be considered as <b>read-only</b>, unless the hook intends to
       
   343 	apply IP-in-IP tunneling, in which case the hook <b>must</b>
       
   344 	change the value to the appropriate tunneling protocol
       
   345 	(#KProtocolInet6Ipip or #KProtocolInetIpip).
       
   346 
       
   347     @par MFlowHook::ReadyL
       
   348 	Only a tunneling hook needs to restore the value here to match
       
   349 	the original upper layer protocol. See #iPacket for
       
   350 	more detailed information.
       
   351 	*/
       
   352 	TUint8 iProtocol;
       
   353 	/**
       
   354 	Selector field whose value depends on #iProtocol. 
       
   355  
       
   356 	If this field does not have meaning with the protocol,
       
   357 	the field content should be set to ZERO.
       
   358 	*/
       
   359 	TUint8 iIcmpType;
       
   360 	/**
       
   361 	Selector field whose value depends on #iProtocol. 
       
   362  
       
   363 	If this field does not have meaning with the protocol,
       
   364 	the field content should be set to ZERO.
       
   365 	*/
       
   366 	TUint8 iIcmpCode;
       
   367 	/**
       
   368 	Selector field whose value depends on #iProtocol. 
       
   369  
       
   370 	If this field does not have meaning with the protocol,
       
   371 	the field content should be set to ZERO.
       
   372 	*/
       
   373 	TUint16 iSrcPort;
       
   374 	/**
       
   375 	Selector field whose value depends on #iProtocol. 
       
   376  
       
   377 	If this field does not have meaning with the protocol,
       
   378 	the field content should be set to ZERO.
       
   379 	*/
       
   380 	TUint16 iDstPort;
       
   381 	/**
       
   382 	The amount of pre-computed IPv6 extension headers in iPacket which
       
   383 	are copied to the beginning of each outgoing packet
       
   384 
       
   385 	If iOffset > 0, then #iPacket includes that much of extension
       
   386 	headers that are copied in front of each packet.
       
   387 	*/
       
   388 	TInt iOffset;
       
   389 	/**
       
   390 	Pre-computed extension headers for all packets in this flow.
       
   391 	
       
   392 	These can only be added in the ReadyL phase. If any of the
       
   393 	ReadyL's adds extension headers into this, it must take care
       
   394 	of maintaining the correct Next Header in the virtual IP header
       
   395 	(and the original upper layer protocol must be placed in the
       
   396 	next header of the last extension header added.
       
   397 	
       
   398 	Stack copies the content of this to each outgoing packet, just below
       
   399 	the IP header, before running the ApplyL functions of the outbound
       
   400 	flow hooks.
       
   401 
       
   402 	@par MIp6Hook::OpenL
       
   403 	The iPacket <b>must not</b> be modified during the OpenL phase.
       
   404 
       
   405 	@par MFlowHook::ReadyL
       
   406 	A non-tunneling hook may add extension headers into the current
       
   407 	iPacket. A tunneling hook has more complex requirements:
       
   408 	it must save the current iPacket and #iOffset and initialize
       
   409 	iOffset = 0, and iPacket as empty.
       
   410 
       
   411     @par MFlowHook::ApplyL
       
   412 	When a tunneling hook adds the tunneling IP header, it
       
   413 	must also copy the saved iPacket below the added IP header.
       
   414 	*/
       
   415 	RMBufPacketPeek iPacket;
       
   416 	/**
       
   417 	The received packet which caused an ICMP error reply to be sent.
       
   418 
       
   419 	This is only used for ICMP error repply flows, and should be
       
   420 	ignored by others -- mainly for IPSEC hook. The packet, if
       
   421 	present, is in unpacked state.
       
   422 	*/
       
   423 	RMBufPacketBase iIcmp;
       
   424 	/**
       
   425 	The current destination interface.
       
   426 
       
   427  	This is ONLY used during connect/OpenL phase.
       
   428 
       
   429 	The value is maintained by the stack, and is intended as
       
   430 	read-only information for the hooks that have a use for
       
   431 	it (for example, IPSEC implementing VPN specific policies).
       
   432 
       
   433 	A hook must not modify this value (the stack will recompute
       
   434 	the value after each OpenL, based on the possibly changed
       
   435 	address parameters in the TPacketHead)
       
   436 
       
   437 	@par MIp6Hook::OpenL
       
   438 	<b>read-only</b>
       
   439 	@par MFlowHook::ReadyL
       
   440 	<b>read-only</b>
       
   441 	*/
       
   442  	TUint32 iInterfaceIndex;
       
   443 	};
       
   444 
   106 
   445 class TInet6PacketBase
   107 class TInet6PacketBase
   446 	/**
   108 	/**
   447 	* Thin base class for the TInet6Packet.
   109 	* Thin base class for the TInet6Packet.
   448 	*/
   110 	*/
   591 	*/
   253 	*/
   592 	T *iHdr;
   254 	T *iHdr;
   593 	};
   255 	};
   594 
   256 
   595 
   257 
   596 //	TPacketPoker
       
   597 //	************
       
   598 class TPacketPoker
       
   599 	/**
       
   600 	Provides a utility for linear scanning of a chain of RMBuf objects (an RMBufChain).
       
   601 
       
   602 	An object of this type maintains a current point in the RMBufChain. This point 
       
   603 	can only move forward, and a leave occurs if the point advances beyond the 
       
   604 	end of the chain.
       
   605 
       
   606 	Any pointers and aligns arranged before the current point, remain valid: for 
       
   607 	example, you can save a reference and advance the pointer, and the reference 
       
   608 	remains usable.
       
   609  
       
   610 	If instead you need to go to a single specified offset, then use
       
   611 	RMBufChain::Goto() or RMBufPacketPeek::Access().
       
   612 
       
   613 	@post
       
   614 	A Generic implementation assert: 
       
   615 	after construct, iTail == 0 iff iCurrent == 0 (all scanned), or
       
   616 	in other words: as long as there are bytes after current point,
       
   617 	iTail will be non-zero (and More() returns ETrue).
       
   618 	All methods maintain this invariant or leave, if impossible.
       
   619 
       
   620 	Some other utility methods, not directly related to scanning, are also included. 
       
   621 	@since v7.0
       
   622 	@publishedAll
       
   623 	@released
       
   624 	*/
       
   625 	{
       
   626 public:
       
   627 	IMPORT_C TPacketPoker(RMBufChain &aChain);
       
   628 
       
   629 	inline void SkipL(TInt aSize)
       
   630 		/**
       
   631 		Moves the current point forward a specified number of bytes.
       
   632 
       
   633 		@param aSize Number of bytes to move forward
       
   634 		@leave KErrEof
       
   635 			if the request cannot be satisfied.
       
   636 		*/
       
   637 		{ if (aSize < iTail) { iTail -= aSize; iOffset += aSize; } else OverL(aSize); }
       
   638 
       
   639 	inline TUint8 *Ptr() const
       
   640 		/**
       
   641 		Raw pointer to the current point (can be invalid, if iTail = 0).
       
   642 	
       
   643 		@note Internal "unsafe" method
       
   644 		*/
       
   645 		{return iCurrent->Ptr() + iOffset; }
       
   646 
       
   647 	inline TUint8 *ReferenceL(TInt aSize = 1)
       
   648 		/**
       
   649 		Gets a pointer to the current point, such that
       
   650 		at least the specified minimum number of bytes can be read.
       
   651 
       
   652 		@param aSize
       
   653 			Specified minimum number of bytes to be read through
       
   654 			the returned pointer.
       
   655 		@return Raw data pointer
       
   656 		@leave KErrEof
       
   657 			if the request cannot be satisfied.
       
   658 		*/
       
   659 		{ if (iTail >= aSize) return Ptr(); else return AdjustL(aSize); }
       
   660 
       
   661 	inline TUint8 *ReferenceAndSkipL(TInt aSize)
       
   662 		/**
       
   663 		Gets a pointer to the current point, such that at least the
       
   664 		specified minimum number of bytes can be read,
       
   665 		and moves the point the specified number of bytes forward.
       
   666 
       
   667 		@param aSize
       
   668 			Specified minimum number of bytes to be read through the returned 
       
   669 			pointer, and the number of bytes to move forward
       
   670 		@return
       
   671 			Raw data pointer
       
   672 		@leave KErrEof
       
   673 			if the request cannot be satisfied.
       
   674 		*/
       
   675 		{ TUint8 *x = ReferenceL(aSize); SkipL(aSize); return x; }
       
   676 
       
   677 	inline TInt Remainder() const
       
   678 		/**
       
   679 		Gets the length of the contiguous space after the current point.	
       
   680 
       
   681 		@return Length after the current point
       
   682 		*/
       
   683 		{ return iTail; }
       
   684 
       
   685 	inline TBool AtBegin() const
       
   686 		/**
       
   687 		Tests whether the current point is at the beginning of an RMBuf.
       
   688 
       
   689 		@return ETrue if current point is at the beginning
       
   690 		*/
       
   691 		{ return iOffset == 0; }
       
   692 
       
   693 	inline TBool More() const
       
   694 		/**
       
   695 		Tests whether there is more data to scan.
       
   696 
       
   697 		@return ETrue if there is more data to scan
       
   698 		*/
       
   699 		{ return iTail > 0; }
       
   700 
       
   701 	IMPORT_C static TBool IsExtensionHeader(TInt aProtocolId);
       
   702 private:
       
   703 	IMPORT_C void OverL(TInt aSize);
       
   704 	IMPORT_C TUint8 *AdjustL(TInt aSize);
       
   705 	/** The RMBuf of the current point. */
       
   706 	RMBuf *iCurrent;
       
   707 	/** The offset of the current point in the RMBuf. */
       
   708 	TInt iOffset;
       
   709 	/** Remaining bytes starting from the current point in the RMBuf. */
       
   710 	TInt iTail;
       
   711 	};
       
   712 
       
   713 #endif
   258 #endif