networkprotocols/iphook/inhook6/include/flow.h
changeset 0 af10295192d8
child 5 1422c6cd3f0c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/iphook/inhook6/include/flow.h	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,1097 @@
+// Copyright (c) 2004-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:
+// flow.h - IPv6/IPv4 flow information
+// IPv6/IPv4 flow information.
+//
+
+
+
+/**
+ @file flow.h
+ @publishedPartner
+ @released
+*/
+
+#ifndef __FLOW_H__
+#define __FLOW_H__
+
+#define SYMBIAN_NETWORKING_UPS
+
+#include <es_prot.h>
+#include <nifmbuf.h>
+#include "in_pkt.h"
+#include "apibase.h"
+
+//
+//	TFlowStatus
+//
+/**
+* Type of the flow status (some symbolic enum names).
+* @since v7.0
+* @publishedPartner
+* @released
+*/
+enum TFlowStatus
+	{
+	/**
+	* (< 0) Flow is in error state.
+	*
+	* All other system wide error codes also indicate a flow error state. 
+	* To recover, the flow must be reconnected.
+	*/
+	EFlow_DOWN = KErrNotReady,
+	/**
+	* (= 0) Flow is ready to send data.
+	*/
+	EFlow_READY = 0,
+	/**
+	* (= 1) Flow is temporarily blocked.
+	*
+	* This is used when the flow is waiting for the connection setup. 
+	* When there is a possibility that flow could change into EFLow_READY
+	* state, the notifier is notified with MProviderNotify::CanSend().
+	*/
+	EFlow_PENDING = 1,
+	/**
+	* (= 2) Flow is temporarily blocked.
+	*
+	* This is used when the flow is blocked due to congestion (e.g. lower level 
+	* buffers are full). When congestion clears and if there is a possibility
+	* that flow could change into EFLow_READY state, the notifier is notified
+	* with MProviderNotify::CanSend().
+	*/
+	EFlow_HOLD = 2
+#ifdef SYMBIAN_TCPIPDHCP_UPDATE
+	,
+    EFlow_NOTCONFIGURE = 3
+#endif //SYMBIAN_TCPIPDHCP_UPDATE    
+	};
+
+//	MProviderNotify
+//	***************
+class MProviderNotify : public MInetBase
+	/**
+	* Receiver of the notifications of the status changes in the flow.
+	*
+	* Note that the two functions CanSend() and Error() are a subset of MSocketNotify. This allows 
+	* a Service Access Point to implement the interface just by calling the equivalent 
+	* MSocketNotify functions. 
+	* @since v7.0
+	* @publishedPartner
+	* @released
+	*/
+	{
+public:
+	/**
+	* Flags that the flow might be ready to change into the EFlow_READY status
+	*
+	* The flow is (or has been) in EFlow_PENDING or EFlow_HOLD state. The flow
+	* owner can now check if flow really can be changed into EFlow_READY state.
+	* The state is updated by calling RFlowContext::Status (or some other functions
+	* that implicitly refresh the flow state by calling internally the
+	* CFlowContext::RefreshFlow function).
+	*
+	* Even if this function is called, the flow can still be in error or blocked
+	* state. This is because, for example, when congestion clears, all flows
+	* waiting for that event are notified, but some earlier notified flow may
+	* already have refilled all the buffers.
+	*/
+	virtual void CanSend() = 0;
+	/**
+	* The flow has entered an error state.
+	*
+	* Error state in a flow is permanent and requires a new connect (CFlowContext::Connect)
+	* to be cleared. A new connect occurs implicitly at FlowContext::Status (or some
+	* at some other functions), if flows connection parameters have been modified
+	* since the last connect (CFlowContext::iChanged is 1).
+	*
+	* @param aError Flow error code
+	* @param anOperationMask A bitmask of MSocketNotify::TOperationBitmasks values 
+	* specifying which pending operations are affected by the error up-call.
+	*/
+	virtual void Error(TInt aError, TUint anOperationMask=MSocketNotify::EErrorAllOperations) = 0;
+	virtual void NoBearer(const TDesC8& aConnectionParams) = 0;
+	virtual void Bearer(const TDesC8 &aConnectionInfo) = 0;
+	virtual TInt CheckPolicy(const TSecurityPolicy&, const char *) 
+		{
+		return KErrNone;
+		};
+	};
+
+
+//
+//	RFlowContext
+//	************
+//
+class MFlowManager;
+class CFlowContext;
+class CNifIfBase;
+
+//	*WARNING*:
+//		Because RFlowContext is used as a member of RMBufSendInfo, which may
+//		get moved around, the RFlowContext handle *MUST* not contain anything
+//		that breaks if it is copied bit-by-bit from one memory area to another!
+//		(for example don't even think of adding link fields and linking
+//		RFlowContext's into a list!) -- msa
+//
+class RFlowContext
+	/**
+	* A handle to a flow context.
+	*
+	* The main purpose of this class is to provide automatic reference counting 
+	* for flow context users.
+	*
+	* A typical use for a RFlowContext object is to:
+	* @li	allocate a context to a handle through the flow manager (Open())
+	* @li	set appropriate flow parameters (the upper layer protocol associated with 
+	* 		the flow, destination and source addresses)
+	* @li 	use the flow to send packets out
+	* @li 	release the context (Close()) from the handle. 
+	* @since v7.0
+	* @publishedPartner
+	* @released
+	*/
+	{
+public:
+	inline RFlowContext() : iFlow(0)
+		/**
+		* Default constructor.
+		*
+		* This creates a handle without any assigned flow context.
+		*/
+		{}
+	IMPORT_C TInt Open(MFlowManager *aManager, const TSockAddr &aDst, const TSockAddr &aSrc, TUint aProtocol = 0, TUint aIcmpType = 0, TUint aIcmpCode = 0);
+	IMPORT_C TInt Open(MFlowManager *aManager, TUint aProtocol = 0);
+	IMPORT_C TInt Open(RFlowContext &aContext, RMBufPktInfo *aInfo = NULL);
+	IMPORT_C TInt Clone(const RFlowContext &aFlow);
+	IMPORT_C TInt ReOpen();
+	IMPORT_C TInt Connect();
+
+	inline TBool IsOpen()
+		/**
+		* Tests if context is attached
+		*/
+		{return iFlow != NULL;}
+
+	IMPORT_C void SetRemoteAddr(const TSockAddr &aAddr);
+	IMPORT_C void SetLocalAddr(const TSockAddr &aAddr);
+	IMPORT_C void SetProtocol(TUint aProtocol);
+	IMPORT_C void SetIcmpType(TUint aType, TUint aCode = 0);
+	IMPORT_C MProviderNotify *SetNotify(MProviderNotify *aProvider);
+	IMPORT_C TInt Status();
+	IMPORT_C void Grab(RFlowContext &aContext);
+	IMPORT_C void Copy(RFlowContext &aContext);
+	IMPORT_C void Close();
+	IMPORT_C CNifIfBase *Interface() const;
+	
+#ifdef SYMBIAN_TCPIPDHCP_UPDATE
+	IMPORT_C TBool IsNdResolutionPending(); //RFC 4861 - Section 7.2.2
+#endif //SYMBIAN_TCPIPDHCP_UPDATE
+	inline CFlowContext *FlowContext() const
+		/** Gets a pointer to the flow context object (CFlowContext)
+		* attached to the handle.
+		*
+		* This can be used for more detailed control of the flow parameters.
+		*
+		* The returned pointer has limited validity,
+		* and it should not be stored in any members of permanent objects.
+		* In addition, care must be taken not to call any operation that could
+		* destroy the flow context as a side effect.
+		*
+		* If there is a need for longer validity of the retrieved pointer,
+		* the CFlowContext::Open and CFlowContext::Close methods can be used
+		* to protect it.
+		*
+		* @return
+		*		The flow context object.
+		*/
+		{ return iFlow; }
+private:
+	/** The flow context. */
+	CFlowContext *iFlow;
+	};
+
+
+
+//	******************************
+//	RMBufSendInfo, RMBufSendPacket
+//	******************************
+class RMBufSendInfo : public RMBufPktInfo
+	/**
+	* Information for outgoing packets.
+	*
+	* This extends the packet information class to record the flow context. 
+	* @since v7.0
+	* @publishedPartner
+	* @released
+	*/
+	{
+public:
+	/** Flow context for the packet. */
+	RFlowContext iFlow;	
+	};
+
+/** @since v5.0 */
+typedef class RMBufInfoPacketBase<RMBufSendInfo> RMBufSendPacket;
+
+// TFlowInfo
+// *********
+class TFlowInfo
+	/**
+	* Collects the information which defines a flow 
+	* (The Upper Layer Flow Information). This is a
+	* member of CFlowContext.
+	*
+	* @since v7.0s
+	*/
+	{
+public:
+	/**
+	* Current remote addess as set by upper layer.
+	*
+	* Must always be specified before a flow can be connecte or
+	* used for sending packets.
+	*
+	* See RFlowContext::SetRemoteAddr, CFlowContext::RemoteAddr
+	*/
+	TInetAddr iRemote;
+	/**
+	* Current local address (system or application selected).
+	*
+	* See RFlowContext::SetLocalAddr, CFlowContext::LocalAddr
+	*/
+	TInetAddr iLocal;
+	/**
+	* The protocol associated with the flow.
+	*
+	* See RFlowContext::SetProtocol, CFlowContext::Protocol
+	*/
+	TUint8 iProtocol;
+	/**
+	* ICMP type, when protocol is ICMP (or similar).
+	*
+	* See RFlowContext::SetIcmpType, CFlowContext::GetIcmpTypeCode
+	*/
+	TUint8 iIcmpType;
+	/**
+	* ICMP code, when protocol is ICMP (or similar).
+	*
+	* See RFlowContext::SetIcmpType, CFlowContext::GetIcmpTypeCode
+	*/
+	TUint8 iIcmpCode;
+	/**
+	* Set when upper layer set the local address.
+	*
+	* When set, the stack assumes the upper layer has specified
+	* the source address of the flow. When not set, the stack
+	* chooses the source address.
+	*
+	* This flag is cleared or set by the RFlowContext::SetLocalAddr().
+	* The flag is cleared when address is unspecified and set otherwise.
+	* Initial value is unset, if SetLocalAddr is never called.
+	*
+	* See also CFlowContext::IsLocalSet
+	*/
+	TUint iLocalSet:1;
+	/**
+	* Set when interface errors should not affect the flow.
+	*
+	* When an interface goes down (or reports an error), all flows
+	* that are currently connected (routed) to this interface, are
+	* also set into error error state (effectively, causing a
+	* socket error to the applications).
+	*
+	* When this flag is set, flow is not set to the error state. However,
+	* if interface is going down, the flow is put into hold/pending
+	* state (until another or same interface becomes again available).
+	*
+	* See also the socket option: #KSoNoInterfaceError
+	*/
+	TUint iNoInterfaceError:1;
+	/**
+	* Set when this flow should not try to bring up the interface.
+	*
+	* When a connect is attempted on a flow and it fails due to
+	* missing routes (no suitable interfaces up or configured yet), the
+	* stack signals the NIFMAN (NoBearer notify function).
+	*
+	* When this flag is set, NIFMAN is not notified and the flow is
+	* just placed into hold/pending state to wait for possible interface
+	* or route to appear.
+	*
+	* @note
+	*	NoBearer does not exisit in pre 7.0s systems. In such
+	*	systems the stack itself activates the "netdial process" in
+	*	this situation.
+	*/
+	TUint iNoInterfaceUp:1;
+	/**
+	* Set when flow is used for packet forwarding.
+	*
+	* This flag, when set, disables the source address checking.
+	* Normally the stack works in "strong model" and requires that
+	* a packet has a valid source address on the interface.
+	* Forwarded packets have other than local source address and
+	* the check must be disabled.
+	*
+	* This can only be set internally or from the hooks. There is no
+	* application level socket option to set this.
+	*/
+	TUint iForwardingFlow:1;
+	// Note! Cannot use TScopeType below, because it would make the
+	// bitfield into signed and fail on tests like:
+	//		x.iLockType == EScopeType_NET
+	// even if x.iLockType has value EScopeType_NET!!! -- msa
+	/**
+	* Locked scope-1 (0..15) [TScopeType].
+	*
+	* This valid only when iLockId is non-zero.
+	*/
+	TUint iLockType:4;
+	/**
+	* Current Locking Id.
+	*
+	* Value ZERO is unlocked. Non-Zero value is a zone id in the scope
+	* specified by iLockType.
+	*/
+	TUint32 iLockId;
+	};
+
+
+//	************
+//	CFlowContext
+//	************
+//	A base class of the Flow Context, cannot be instantiated as is
+//
+class COptionValue;
+class MFlowHook;
+class MInterfaceManager;
+
+class CFlowContext : public CBase
+	/**
+	* The flow context instance.
+	*
+	* The CFlowContext has several public methods, but not all of them are safe
+	* (or even legal) to use in all situations.
+	*
+	* CFlowContext is a reference counted object. Whenever a pointer is
+	* stored for long term duration, the Open() must be called, and when
+	* pointer is no more used, a close must be called. This object is only
+	* deleted indirectly via use of Close(). The delete operator is never
+	* used explicitly from outside.
+	*
+	* Base class for a flow context.
+	* @since v7.0
+	* @publishedPartner
+	* @released
+	*/
+	{
+	friend class MFlowManager;
+	friend class RFlowContext;
+protected:
+ 	IMPORT_C CFlowContext(const void *aOwner, MFlowManager *aManager);
+ 	IMPORT_C CFlowContext(const void *aOwner, MFlowManager *aManager, CFlowContext &aFlow);
+	// Destructor should not be exported, it should be private! -- msa
+	IMPORT_C virtual ~CFlowContext();
+
+#ifdef SYMBIAN_NETWORKING_UPS
+	/**
+	Indicate whether the flow has a provider above it.
+	@return ETrue if it has, else EFalse.
+	*/
+	inline TBool HasProvider() const;
+	
+	
+	inline void *GetProviderApiL(const TDesC8& aApiName, TUint* aVersion);
+#endif //SYMBIAN_NETWORKING_UPS
+
+public:
+	IMPORT_C void Close();
+
+	inline void Open()
+		/**
+		* Increments a reference count on the context
+		*/
+		{ iRefs++; }
+	IMPORT_C TInt Status();
+	IMPORT_C void SetStatus(TInt aStatus);
+	IMPORT_C TInt StoreOption(TUint aLevel, TUint aName, const TDesC8 &aOption);
+	IMPORT_C TInt RetrieveOption(TUint aLevel, TUint aName, TDes8 &aOption) const;
+
+	inline TPacketHead &Head()
+		/**
+		* Gets access to precomputed information for the outbound packet flow.
+		*
+		* @return Precomputed information for the outbound packet flow
+		*/
+		{ return iHead; }
+
+	/**
+	* @defgroup	getselectors	Retrieve current selector fields
+	*
+	* @{
+	*/
+
+ 	inline TUint LocalPort() const
+		/**
+		* Gets the flow's local port.
+		* @return current local port
+		*/
+		{ return iInfo.iLocal.Port(); }
+
+	inline TUint RemotePort() const
+		/**
+		* Gets the flow's remote port.
+		* @return current remote port
+		*/
+		{ return iInfo.iRemote.Port(); }
+
+	inline TUint Protocol() const
+		/**
+		* Gets the flow protocol.
+		* @return current protocol
+		*/
+		{ return iInfo.iProtocol; }
+
+	inline const TInetAddr &LocalAddr() const
+		/**
+		* Gets the flow's local address.
+		*
+		* The local address may have been selected by the system, if
+		* the transport layer didn't set it (left it unspecified or
+		* explicitly set unspecified address to it).
+		*
+		* @note
+		*	All addresses in the flow context are kept in IPv6 format
+		*	(using IPv4 mapped addresses for IPv4 flows).
+		*
+		* @return Local address.
+		*/
+		{ return iInfo.iLocal; }
+
+	inline TBool IsLocalSet() const
+		/**
+		* Gets the flow's local address status.
+		*
+		* The local address can be selected by the stack, or application
+		* can have set it into a specific value. When this address status
+		* have value ETrue, the stack assumes that the local address has
+		* been chosen by the application or upper layer protocol. When
+		* status is EFalse, the stack selects the source
+		* address for the flow when the flow is connected
+		* (CFlowContext::Connect).
+		*
+		* The RFlowContext::SetLocalAddress will set this status to EFalse,
+		* if the address is unspecified address, and to ETrue otherwise.
+		*
+		* @note
+		*	If an application requires using the unspecified source address
+		*	in packets (IPv4 <tt>0.0.0.0</tt> or IPv6 <tt>::</tt>), it must use
+		*	the socket option #KSoNoSourceAddressSelect (level #KSolInetIp)
+		*	<em>after</em> it has performed the RSocket::Bind() to uspecified
+		*	address.
+		*
+		* Some upper layer protocols may also set this status, after the
+		* connection is established (TCP).
+		*
+		* @return ETrue, if local addr is set
+	 	*/
+		{ return iInfo.iLocalSet != 0; }
+
+	inline const TInetAddr &RemoteAddr() const
+		/**
+		* Gets the flow's remote address.
+		*
+		* @return Remote address.
+		*/
+		{ return iInfo.iRemote; }
+		
+	inline void GetIcmpTypeCode(TUint8 &aType, TUint8 &aCode) const
+		/**
+		* Gets the flow's ICMP type and code.
+		*
+		* @retval aType	Icmp (or other) type
+		* @retval aCode	Icmp (or other) code
+		*/
+		{ aType = iInfo.iIcmpType; aCode = iInfo.iIcmpCode; }
+
+	inline TScopeType LockType() const
+		/**
+		* Gets the flow's locking type [0..15].
+		*
+		* The locking type tells the type of the lock id. The type has no
+		* meaning if the lock id has zero value (= flow is not locked)..
+		*
+		* @return current type of LockId (IF=0, IAP=1, NET=15).
+		*/
+		{ return (TScopeType)iInfo.iLockType; }
+
+	inline TUint32 LockId() const
+		/**
+		* Gets the flows lock id.
+		*
+		* A flow can be locked to a specified scope. When locked (non-zero),
+		* the flow can only be connected to an interface within the locked
+		* scope.
+		*
+		* The id value is a plain 32 bit number and the domain of this
+		* value is defined by the locking type (CFlowContext::LockType).
+		*
+		* @return current lock id (IAP, NET or IF). Not locked, if ZERO
+		*/
+		{ return iInfo.iLockId; }
+
+	/** @} */
+
+	/**
+	* @defgroup packetsize	Accessing parameters of the packet size
+	*
+	* In all, return
+	*	@li	< 0, indicates an error or value not known
+	*	@li	= 0, (interpretation not fixed)
+	*	@li	> 0, the indicated value
+	*
+	* Some assertations that should be true
+	*	@li	PathMtu() > HeaderSize()
+	*	@li	HeaderSize() >= sizeof(TInet6HeaderIP)
+	*	@li	InterfaceSMtu() >= PathMTU()
+	*	@li	InterfaceRMtu() > sizeof(TInet6HeaderIP)
+	*
+	* @{
+	*/
+
+	inline TInt PathMtu() const
+		/**
+		* Gets the Path MTU of the flow.
+		*
+		* @return
+		* @li	< 0,    indicates an error or value not yet known (for example,
+		*				if accessed before the flow is connected or interface is up)
+		* @li	= 0,    value not known
+		*
+		* @li	> 0,     a real value
+		*/
+		{ return iPathMtu; }
+
+	inline TInt HeaderSize() const
+		/**
+		* Gets the amount of the protocol overhead in the packet from all of the lower layers.
+		*
+		* The value is defined only for a flow that has been connected.
+		* (CFlowContext::Connect).
+		*
+		* HeaderSize () > 0 (at least IPv4 or IPv6 header size)
+		*
+		* @return
+		* @li	< 0,    indicates an error or value not yet known (for example,
+		*				if accessed before the flow is connected or interface is up)
+		* @li	= 0,    value not known
+		* @li	> 0,	a real value
+		*/
+		{ return iHdrSize; }
+	
+	/**
+	* Gets the raw send MTU of the attached interface.
+	*
+	* The value is defined only for a flow that has been connected.
+	* (CFlowContext::Connect).
+	*
+	* @return
+	* @li	< 0,    indicates an error or value not yet known (for example,
+	*				if accessed before the flow is connected or interface is up)
+	* @li	= 0,    value not known
+	* @li	> 0,	a real value
+	*/
+	virtual TInt InterfaceSMtu() const = 0;
+	/**
+	* Gets the raw receive MTU of the interface.
+	*
+	* The value is defined only for a flow that has been connected.
+	* (CFlowContext::Connect).
+	*
+	* @return
+	* @li	< 0,    indicates an error or value not yet known (for example,
+	*				if accessed before the flow is connected or interface is up)
+	* @li	= 0,    value not known
+	* @li	> 0,	a real value
+	*/
+	virtual TInt InterfaceRMtu() const = 0;
+	/** @} */
+
+	/**
+	* Gets an option from the flow context.
+	*
+	* A set of options can be read from the flow context.
+	*
+	* In addition to internally supported options,
+	* any registered outbound hook can add support for additional options
+	* (see MIp6Hook::GetFlowOption documentation).
+	*
+	* The function is called part of the normal option processing.
+	*
+	* @param aLevel The option level
+	* @param aName The option name
+	* @param aOption The option value
+	* @return
+	*		KErrNone, or KErrNotSuppoted if option cannot be read from the flow context.
+	*/
+	virtual TInt GetOption(TUint aLevel, TUint aName, TDes8 &aOption) const = 0;
+
+	/**
+	* Sets an option to the flow context.
+	*
+	* A set of options can be set to the flow context.
+	*.
+	* In addition to internally supported options,
+	* any registered outbound hook can add support for additional options
+	* (see MIp6Hook::SetFlowOption documentation).
+	*
+	* The function is called part of the normal option processing.
+	*
+	* @param aLevel The option level
+	* @param aName The option name
+	* @param aOption The option value
+	* @return
+	*		KErrNone, or KErrNotSuppoted if option cannot be set from the flow context.
+	*/
+	virtual TInt SetOption(TUint aLevel, TUint aName, const TDesC8 &aOption) = 0;
+
+	/**
+	* Gets the currently connected interface.
+	*
+	* @return
+	*		The currently connected interface,
+	*		if the flow is properly connected, otherwise NULL.
+	*		The returned pointer has limited validity, and it should not be stored
+	*		in any members of permanent objects.
+	*/
+	virtual CNifIfBase *Interface() const = 0;
+
+	/**
+	* Gets the interface manager of the TCP/IP stack..
+	*
+	* @return
+	*		The interface manager.
+	*/
+	virtual MInterfaceManager *Interfacer() const = 0;
+
+	/**
+	* Sends a packet to the attached interface.
+	*
+	* This is a low level function intended for the IP layer itself.
+	* Send bypasses all the installed hooks and path mtu processing.
+	* The raw data in the packet is passed to the interface as is.
+	* (for the normal way of sending a packet, see MNetworkService::Send).
+	*
+	* If the flow is not connected, the Send drops the packet and the
+	* return is KErrNotReady.
+	*
+	* The destination address of the information block may get changed
+	* into link layer destination address, if the stack is handling the
+	* neighbour discovery on the link (ARP for IPv4, ICMPv6 Neighbor
+	* discovery for IPv6).
+	*
+	* If the destination is a multicast address, and if that address
+	* is also joined by some application(s), then a copy of the packet
+	* is sent to the inbound direction (MNetworkService::Process),
+	* unless disabled by #KSoIp6MulticastLoop socket option.
+	*
+	* @param aPacket
+	*		The data packet (assumed to be RMBufInfoPktBase in "packed" state)
+	* @param aSource
+	*		The source protocol instance (passed as is to the interface). Optional,
+	*		and usually NULL.
+	* @return
+	*		is defined similarly as the equivalent methods of the interfaces and
+	*		protocols, as follows:
+	* @li	< 0,
+	*		an error: the packet is not sent, but is dropped by Send().
+	* @li	= 0,
+	*		indicates that the interface received the packet, but is also signaling
+	*		that its reluctance to receive more packets. All flows attached to this
+	*		interface are automatically set into EFlow_HOLD state.
+	* @li	> 0,
+	*		indicates that the interface received the packet and is willing to
+	*		receive more after this.
+	*/
+	virtual TInt Send(RMBufChain &aPacket, CProtocolBase* aSource = NULL) = 0;
+
+	/** Attaches a flow to a route and an interface. */
+	virtual void Connect() = 0;
+	/** Disconnects the flow, and remove all hooks. */
+	virtual void Disconnect() = 0;
+	/** Recomputes the current flow status. */
+	virtual void RefreshFlow() = 0;
+	/**
+	* Sets "changed" state to flow(s).
+	*
+	* Sets the iChanged flag that indicates that connect information has changed.
+	* 
+	* When any component of the system determines that a flow or set
+	* of flows require an open phase (reconnect), the component can use the
+	* this function to force a reconnect of the flow on the next outgoing packet.
+	*
+	* @param aScope determines what flows are affected:
+	* @li	0: set iChanged on current flow
+	* @li	1: set iChanged on all flows with same route entry,
+	* @li	2: set iChanged on all flows with same interface,
+	* @li	> 2: set iChanged on all existing flows
+	*
+	* @return
+	*		Number of flows affected (regardless of their previous iChanged state)
+	*/
+	virtual TInt SetChanged(const TInt aScope = 0) = 0;
+#ifdef SYMBIAN_TCPIPDHCP_UPDATE
+	/* RFC 4861: Sec 7.2.2 Verifies any pending ND packets exists on a route during ND
+	 */
+	virtual TBool IsNdPacketPendingResolution() {return EFalse; } ; // Base implementation
+#endif //SYMBIAN_TCPIPDHCP_UPDATE
+	inline void NoBearer(const TDesC8& aConnectionParams);
+	inline void Bearer(const TDesC8 &aConnectionInfo);
+	inline TInt CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic);
+
+protected:
+	/** The owner of the flow (untyped ID data). */
+	const void *const iOwner;
+	/** The flow manager that created this object. */
+	MFlowManager *const iMgr;
+
+	/** Contains the object reference count.
+	* 
+	* For a single reference, this is 0.
+	*/
+	TInt iRefs;
+	/** The flow's status.
+	* 
+	* @li = 0: up and running
+	* @li > 0: pending
+	* @li < 0: error.
+	*/
+	TInt iStatus;
+public:	
+	/** The Upper Layer Flow Information */
+	TFlowInfo iInfo;
+protected:
+	/**	
+	* Set when flow needs a reconnect (selector information changed).
+	*
+	* When this is set (1), RFlowContext::Status (and some other methods) will
+	* automaticly call CFlowContext::Connect for the flow. Primary reason for
+	* this to be set is that the flow selector information has been changed
+	* (@ref setselectors).
+	*
+	* This can be set explicitly by the CFlowContext::SetChanged function (or
+	* MFlowManager::SetChanged).
+	*/
+	TUint iChanged:1;
+public:
+	/**
+	* Flag that indicates that NIF HOLD return should not block the flow.
+	*
+	* After a packet send a NIF can return a value that indicates that no
+	* more packets are to be sent to it, until it allows it again via
+	* the CProtocolBase::StartSending call. Normally, such indication
+	* sets the flow into HOLD state.
+	*
+	* When this flag is set, flow is not put into HOLD. This flag should
+	* only be used by a hook that have other means of enforcing the flow
+	* control (for example QOS).
+	*/
+	TUint iIgnoreFlowControl:1;
+	/** Precomputed packet header information. */
+	TPacketHead iHead;
+	/**
+	* The current Path MTU
+	*
+	* Set from the path MTU of the connected interface. May change
+	* dynamically due to ICMP "packet too big" or other events.
+	*/
+	TUint iPathMtu;
+	/**
+	* The header overhead by IP layer and hooks
+	*
+	* The iHdrSize is initialized to 0 at the beginning of the MIp6Hook::OpenL
+	* phase.
+	* The final value at the end of the OpenL phase is saved, and this value
+	* will be the initial value at the beginning of the MFlowHook::ReadyL phase.
+	*
+	* The final value at the end of the ReadyL phase must be the total amount
+	* of header space required by the layers below the transport (upper layer
+	* protocol). The space available for the upper layer header and payload
+	* is: iPathMtu - iHdrSize.
+	*
+	* The hook can add the header space requirement in OpenL or ReadyL
+	* method. If it does it in OpenL, it does not need to touch the
+	* iHdrSize in ReadyL method (for example, IPSEC only knows the
+	* exact required header space at ReadyL phase).
+	*
+	* If a hook uses the TPacketHead::iPacket member to store precomputed
+	* headers, which are automaticly appended to each packet, it must include
+	* the amount into iHdrSize (it must carefully compute the change of length
+	* in iPacket, if it adds new data there).
+	*
+	* The stack includes implicitly the header space for INNERMOST IP header
+	* (which is also the final IP header, if no tunneling is present). Any hook,
+	* that does tunneling, must include the OUTER IP header requirements into
+	* the iHdrSize (a tunneling hook is ADDING the outer header!).
+	*/
+	TUint iHdrSize;
+private:
+	/** Receives state change upcalls. Also the owner of the flow. */
+	MProviderNotify *iProvider;
+	/** Storage for any other options. */
+	COptionValue *iStorage;
+	};
+
+
+inline void CFlowContext::NoBearer(const TDesC8& aConnectionParams)
+	/** Passes NoBearer call to owner, if present. */
+	{
+	if (iProvider)
+		iProvider->NoBearer(aConnectionParams);
+	}
+inline void CFlowContext::Bearer(const TDesC8 &aConnectionInfo)
+	/** Passes Bearer call to owner, if present. */
+	{
+	if (iProvider)
+		iProvider->Bearer(aConnectionInfo);
+	}
+
+inline TInt CFlowContext::CheckPolicy(const TSecurityPolicy& aPolicy, const char *aDiagnostic)
+	{
+	return iProvider ? iProvider->CheckPolicy(aPolicy, aDiagnostic) : KErrNone;
+	}
+
+#ifdef SYMBIAN_NETWORKING_UPS
+inline TBool CFlowContext::HasProvider() const
+	{
+	return (iProvider != NULL);
+	}
+	
+inline void *CFlowContext::GetProviderApiL(const TDesC8& aApiName, TUint* aVersion)
+	{
+	if (iProvider == NULL)
+		{
+		return NULL;
+		}
+	else
+		{
+		return iProvider->GetApiL(aApiName, aVersion);		
+		}	
+	}
+	
+#endif //SYMBIAN_NETWORKING_UPS
+
+//	*********
+//	MFlowHook
+//	*********
+class MFlowHook : public MInetBase
+	/**
+	* Abstract base class for flow hooks.
+	*
+	* Flow hook providers implement this class. They register the hook using
+	* MIp6Hook::BindFlowHook(), and return an instance from MIp6Hook::OpenL().
+	*
+	* @note
+	*	The same instance of MFlowHook can be returned for multiple flows,
+	*	if the logic of the hook does not require unique instance for each flow.
+	*
+	* The object can be implemented as reference counted object: last reference
+	* removed by Close deletes the object.
+	*
+	* @since v7.0
+	* @publishedPartner
+	* @released
+	*
+	* Example:
+	* @dontinclude mflowhook.cpp
+	* @skip MFlowHook
+	* @until //-
+	*/
+	{
+public:
+	/**
+	* Increment reference count.
+	*
+	* The Open and Close functions must implement a reference
+	* counting system. The Close function must destroy the current
+	* instance, when the last reference is removed.
+	*
+	* Non-NULL return from MIp6Hook::OpenL() counts as one reference, and
+	* the stack is guaranteed to call the matching Close exactly once.
+	*
+	* If a hook creates a new instance for each flow at OpenL, it can
+	* leave the reference count as initial ZERO, if it implements a
+	* Close, which deletes the object when the count goes negative.
+	*
+	* If a hook returns an existing instance at OpenL, it must
+	* increment the reference count by one.
+	*
+	* Example:
+	* @dontinclude mflowhook.cpp
+	* @skip ::Open(
+	* @until //-
+	*/
+	virtual void Open() = 0;
+	/**
+	* On an interface connecting, asks the hook if a flow is ready.
+	*
+	* The ReadyL calls propagate interface ready state up the
+	* flow. The calls to hooks are made in reverse order;
+	* the closest to interface is called first. The call informs
+	* this hook that everything is ready from this hook to the interface.
+	* Now it this hooks turn to check the ready state of the flow.
+	*
+	* @param aHead
+	*		Address information of the flow.
+	* @return
+	*		from the ReadyL is the new status of the flow and has the following
+	*		implications
+	* @li	== 0, hook is ready, proceed to the next one or mark the flow
+	*		as READY, if this was the first hook.
+	* @li	> 0, hook is not ready, the ready calling is stopped and the
+	*		returned value is the (pending) state of the flow.
+	*		The hook MUST send a signal later to release this state to
+	*		reactivate the ReadyL call chain.
+	* @li	< 0, hook detected an unrecoverable error on flow
+	*
+	* @exception
+	*		If the ReadyL leaves, the leave status will become
+	*		the flow status  (the leave status must be negative, or KErrGeneral
+	*		is substituted for it)
+	*
+	* Example:
+	* @dontinclude mflowhook.cpp
+	* @skip ::ReadyL(
+	* @until //-
+	*/
+	virtual TInt ReadyL(TPacketHead &aHead) = 0;
+	/**
+	* Apply send transformations.
+	*
+	* The ApplyL is called by IP protocol  for outbound packet. The aPacket
+	* is in "unpacked" state (RMBufPacketBase::Unpack).
+	*
+	* @param aPacket
+	*		a complete packet to be processed (if needed) by the hook.
+	*		The packet includes the IP header.
+	* @param aInfo
+	*		information block associated with the packet (a hook must not
+	*		break this association!)
+	* @return
+	* @li	= 0,    (KErrNone) hook processed the packet, proceed with the next.
+	* @li	< 0,    (error code) hook discarded the packet for some reason, send is
+	*				aborted.
+	* @li	> 0,    restart hook processing [the actual utility of this is
+	*				still under consideration, maybe removed if no sensible
+	*				use found.]
+	*
+	* @exception
+	*		if ApplyL leaves, the packet is dropped.
+	*
+	* Example:
+	* @dontinclude mflowhook.cpp
+	* @skip ::ApplyL(
+	* @until //-
+	*/
+	virtual TInt ApplyL(RMBufSendPacket &aPacket, RMBufSendInfo &aInfo) = 0;
+	/**
+	* Decrement references and destroy if last.
+	*
+	* Example:
+	* @dontinclude mflowhook.cpp
+	* @skip ::Close(
+	* @until //-
+	*/
+	virtual void Close() = 0;
+	};
+
+class CFlowInternalContext;
+
+class MFlowManager : public MInetBase
+	/**
+	* The flow manager interface.
+	*
+	* The use of MFlowManager is mostly hidden behind the RFlowContext,
+	* but the upper layer must be aware of its existence.
+	* Currently, the MFlowManager interface is included into the MnetworkService
+	* (and is implemented by the IP6 protocol instance),
+	* which must be used whenever an instance of MFlowManager is required.
+	* @since v7.0
+	* @publishedPartner
+	* @released
+	*/
+	{
+public:
+	/**
+	* Increase the "users" counter.
+	*
+	* The count of current "users" is used in determining whether to
+	* keep or release resources. This in turn, may cause the disconnect
+	* of a data connection.
+	*
+	* The stack leaves it up to the upper layers to decide what is counted as a 
+	* "user". IncUsers() and DecUsers() should be used to give this information 
+	* to the underlying system. By default, each opened socket is counted as
+	* one user.
+	*/
+	virtual void IncUsers() = 0;
+	/**
+	* Decrease the "users" counter.
+	* For details, see IncUsers().
+	*/
+	virtual void DecUsers() = 0;
+	//
+	// Use of the following methods is through the
+	// RFlowContext handle
+	//
+	/**
+	* Creates a new (empty) instance of a CFlowContext.
+	*
+	* @param aOwner Identifies the flow's owner (typically an RFlowContext handle)
+	* @param aProtocol Protocol ID
+	* @return New object
+	*/
+	virtual CFlowContext *NewFlowL(const void *aOwner, TUint aProtocol) = 0;
+	/**
+	* Creates a copy of an instance of a CFlowContext.
+	*
+	* @param aOwner Identifies the flow's owner (typically an RFlowContext handle)
+	* @param aFlow Object to copy
+	* @return New object
+	*/
+	virtual CFlowContext *NewFlowL(const void *aOwner, CFlowContext &aFlow) = 0;
+	/**
+	* Sets the connect information changed flag on all flows.
+	* @return Number of flows.
+	*/
+	virtual TInt SetChanged() const = 0;
+
+
+//protected:
+
+	/** Internal API between flow and flow manager. @publishedPartner */
+	virtual TInt FlowSetupHooks(CFlowInternalContext &aFlow) = 0;
+	/** Internal API between flow and flow manager. @publishedPartner */
+	virtual void FlowStartRefresh(CFlowInternalContext &aFlow) = 0;
+	//
+	// Flow option handling
+	//
+	/** Internal API between flow and flow manager. @publishedPartner */
+	virtual TInt GetFlowOption(TUint aLevel, TUint aName, TDes8 &aOption, const CFlowContext &aFlow) const = 0;
+	/** Internal API between flow and flow manager. @publishedPartner */
+	virtual TInt SetFlowOption(TUint aLevel, TUint aName, const TDesC8 &aOption, CFlowContext &aFlow) = 0;
+	};
+
+#endif