--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/iphook/inhook6/include/ip6_hook.h Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,846 @@
+// 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:
+// ip6_hook.h - hook interface for IPv6 extension header handlers
+// This module defines the interface between the main IPv6 protocol
+// handler (ip6.cpp) and header handlers. A hook need only the basic
+// IPv6 header definitions (ip6_hdr.h), it does not need to be aware
+// of IPv6 protocol specific classes: it should not include ip6.h!
+// This describes a pure interface, there is no respective
+// implementation module (ip6_hook.cpp does not exist).
+//
+
+
+
+/**
+ @file ip6_hook.h
+ @publishedPartner
+ @released
+*/
+
+#ifndef __IP6_HOOK_H__
+#define __IP6_HOOK_H__
+
+#include <es_prot.h>
+#include <nifmbuf.h> // The interface uses RMBuf with Info
+#include "inet6err.h"
+#include "flow.h"
+#include "ip6_iprt.h" // ..for CProtocolBaseUnbind class.
+#include "apibase.h"
+
+/** @name IP v6 constants
+* @since v7.0
+*/
+//@{
+
+/**
+* A reference constant used to compute protocol ID values for the CProtocolBase::BindL()
+* method of the IP protocol.
+*/
+const TInt KIp6Hook_ANY = 256;
+
+/**
+* A special return value from MIp6Hook::ApplyL().
+*
+* This signals that the hook didn't handle the extension header,
+* which will be passed to the next registered hook
+*/
+const TInt KIp6Hook_PASS = 0;
+
+/**
+* A special return value from MIp6Hook::ApplyL().
+*
+* This signals that the hook processed the extension header and
+* that the main loop should restart a new hook processing using
+* the function's aInfo.iProtocol field.
+*/
+const TInt KIp6Hook_DONE = 1;
+
+/**
+* A flag that must be <b>cleared</b> by MIp6Hook::ApplyL() processing
+* in the aInfo.iFlags parameter, if the hook changes the destination or
+* source address in the aInfo.
+*
+* It causes address and forwarding checks to be run by the main loop.
+*
+* Note that this requires the hook to also signal that the extension
+* header has been processed by returning KIp6Hook_DONE.
+*/
+const TUint KIpAddressVerified = 0x080000;
+//
+// *NOTE* This flag is added as a stopgap solution for
+// the IPSEC problem, which results if decrypted packet
+// is echoed pack due to some error condition (like
+// Port Unreachable). It may be removed when a final
+// solution for the problem is found (and if no other
+// uses exist). -- msa
+/**
+* Prevent sending of this packet as ICMP error report.
+*
+* A flag that if set causes an unconditional drop of a packet,
+* if the packet is passed to the ICMP send functionality in
+* the IP layer. (see MNetworkService::Icmp4Send or
+* MNetworkService::Icmp6Send
+*/
+const TUint KIpNeverIcmpError = 0x100000;
+// *NOTE*
+// Reuse the same bit as KIpAddressVerified. This
+// is ok, because verified bit is used only for incoming
+// packets, and the keep up is used only for outgoing packets.
+//
+/**
+* KIpKeepInterfaceUp is an internal flag which set or reset
+* depending on the state of the KSoKeepInterfaceUp option.
+*/
+const TUint KIpKeepInterfaceUp = 0x080000;
+
+/**
+* If this bit is set in RMBufPktInfo flags, the ECN ECT bits in
+* IP packet should be zeroed.
+*/
+const TUint KIpNoEcnEct = 0x200000;
+//@}
+
+//
+// RMBufRecvInfo
+// *************
+class RMBufRecvInfo : public RMBufPktInfo
+/**
+* Information for incoming packets.
+*
+* This extends the packet information class to record progress of
+* processing the received IPv4 or IPv6 packet.
+*
+* The RMBufChain contains a full IPv6 (or IPv4) packet
+* starting from the beginning. The position of the current
+* (upper layer or extension header) is indicated by the
+* #iOffset field.
+*
+* @li #iProtocol
+* is always the internet protocol number corresponding
+* to the header incidated by iOffset.
+*
+* @li #iLength
+* is the length of the FULL packet, starting from the
+* IP header. The upper layer length (that includes
+* the uppler layer header) is always: (iLength - iOffset) >= 0.
+* Note that this can be ZERO!
+*
+* @li #iIcmp == 0, for normal packet
+*
+* @li #iIcmp =! 0, for ICMP error report
+*
+* The source and destination address are loaded from the ip
+* header associated with the indicated upper layer header. In
+* case of ICMP error report, the addresses are loaded from the
+* packet *inside* the ICMP report.
+*
+* The addresses are always in IPv6 format. If the packet
+* was IPv4 packet, the addresses are presented in IPv4 mapped format.
+*
+* @warning
+* The fact that address is IPv4 mapped DOES NOT mean that
+* the packet is IPv4. It could as well be an IPv6
+* packet with mapped addresses!
+*
+* @warning
+* RMBufRecvInfo is assuming that it fits
+* into the single RMBuf block.
+*
+* @publishedPartner
+* @released
+* @since v7.0
+*/
+ {
+public:
+ TInt CheckL(TInt aLength) const
+ /**
+ * Tests that the specified length field does not exceed the
+ * remaining space in the buffer.
+ *
+ * Verify that there is enough data after in the packet
+ * after the #iOffset octets. This simply tests whether
+ * (aLength > #iLength - #iOffset), and leaves
+ * with #KErrInet6ShortPacket, if true.
+ *
+ * @param aLength Length to test.
+ * @return aLength (for convenience)
+ * @leave KErrInet6ShortPacket Insufficient space.
+ */
+ {
+ if (aLength > iLength - iOffset)
+ User::Leave(KErrInet6ShortPacket);
+ return aLength;
+ }
+ /** Index of the logical source network interface. */
+ TUint32 iInterfaceIndex;
+ /** Index of the physical original network interface. */
+ TUint32 iOriginalIndex;
+ //
+ // IP Information
+ //
+ /**
+ * An offset that indicates the beginning of the current header
+ * being processed.
+ *
+ * Inbound hooks must update this if they consume a header
+ * within the packet.
+ *
+ * It initially points to the first header after the IP header.
+ * Offset to the header being processed.
+ */
+ TInt iOffset;
+ /**
+ * Offset to the related IP header.
+ *
+ * This is usually zero, but is non-zero for ICMP error reports, and could be
+ * non-zero for tunneled packets.
+ */
+ TUint16 iOffsetIp;
+ /** Offset of the previous Next Header field.
+ *
+ * If a hook consumes an extension header and advances #iOffset to the
+ * next header, it must also set this to point to the Next Header
+ * field of the former header.
+ *
+ * This is initialized to refer the next header field of the IP header.
+ *
+ * This can be used by header handlers which remove the
+ * header from the packet. For example, IPSEC does this for AH and
+ * ESP headers. IPSEC must be able to correct the protocol/next header
+ * field of the previous header.
+ */
+ TUint16 iPrevNextHdr;
+ /**
+ * IP Version (4 or 6) of the related IP header.
+ */
+ TUint8 iVersion;
+ /**
+ * ICMP packet flag.
+ *
+ * This determines the interpretation of the information fields:
+ * iType, iCode, and iParameter.
+ *
+ * @li
+ * iIcmp == 0, The buffer contains normal upper layer packet,
+ * the header starting from the indicated iOffset.
+ * The values of the iType, iCode and iParameter are undefined..
+ *
+ * @li
+ * iIcmp != 0, The buffer contains an ICMP error report for
+ * the upper layer protocol, the returned upper layer header
+ * starting from the indicated iOffset. The #iOffsetIp indicates
+ * the start of the problem packet.
+ *
+ * Valid values are: 0, #KProtocolInetIcmp, or #KProtocolInet6Icmp.
+ */
+ TUint8 iIcmp;
+ /**
+ * ICMP Type (0..255).
+ *
+ * This applies to both ICMPv4 and ICMPv6.
+ *
+ * (only defined if the field iIcmp != 0)
+ */
+ TUint8 iType;
+ /**
+ * ICMP Code (0..255).
+ *
+ * This applies to both ICMPv4 and ICMPv6.
+ *
+ * (only defined if the field iIcmp != 0)
+ */
+ TUint8 iCode;
+ /**
+ * The last 32 bits from the ICMP header.
+ *
+ * (only defined if the field iIcmp != 0)
+ */
+ TUint32 iParameter;
+ };
+
+typedef class RMBufInfoPacketBase<RMBufRecvInfo> RMBufRecvPacket;
+
+
+class MPacketContext : public MInetBase
+/**
+* Provides a packet context as a number of (key, value) pairs.
+*
+* The rules for construction of the key are:
+* @li
+* The low eight bits of the key contain always the protocol number
+* (extension header) being implemented by the hook.
+* @li
+* If the protocol is destination option or hop-by-hop option,
+* the implemented option types are communicated to the default
+* handler by adding a non-zero value to the packet context with
+* a key computed as "(option-type << 8) | protocol".
+*
+* @publishedPartner
+* @released
+* @since v7.0
+*/
+ {
+public:
+ /**
+ * Sets a (key,value) pair.
+ *
+ * If a setting already exists for the key, the value is just replaced.
+ *
+ * @param aId Key
+ * @param aValue Value associated with the key
+ * @return
+ * @li KErrNone, if value stored successfully.
+ * @li KErrNoMemory, if there was no room for the new value
+ */
+ virtual TInt SetHookValue(const TUint32 aId, const TUint32 aValue) = 0;
+ /**
+ * Gets the value associated with the specified key.
+ *
+ * Return the current value associated with aId. If aId does not
+ * exist, ZERO is returned [=> there is no way to differentiate
+ * between non-existing value and a value that is explicitly set
+ * to zero. Implementation may interpret setting value to ZERO
+ * as request to delete the association, if it exists].
+ *
+ * @param aId Key
+ * @return The value, or 0 if no value was found for the key..
+ */
+ virtual TUint32 HookValue(const TUint32 aId) const = 0;
+ };
+
+class RMBufHookPacket : public RMBufRecvPacket
+/**
+* Extends the received packet buffer class for hook processing.
+*
+* The extension provides a packet context (MPacketContext) for
+* the duration of the hook processing.
+*
+* This extension has been created to solve the following problem:
+*
+* -# The default option header handlers need to return ICMP
+* error message on some unimplemented options,
+* -# The basic design idea of the stack is that functionality
+* can be dynamically added. Thus, if a dynamically loaded
+* module adds support for some new option type, the default
+* handler should not report error for such options.
+*
+* The rules of the context use are:
+*
+* -# While the incoming packet is processed with hooks, the IP
+* layer maintains a packet specific context, which can store
+* values (32 bits) associated with a key (32 bits).
+* -# The low 8 bits of the key is defined to be the protocol number
+* of the header, and interpretation of the rest of the key bits
+* is up to protocol/header specific definitions.
+* -# For destination and hop by hop headers, to solve the problem,
+* the additional specification is used: the default handlers will
+* look a value from packet context with the following key:
+* - (optiontype << 8) | (protocol)
+* .
+* and if the returned value is non-ZERO, the default handler
+* will assume someone implemented the option in question and
+* does not generate an error.
+*
+* @note
+* The packet context is only available during "hook processing".
+* It is not available for upper layer prototocols!
+*
+* @publishedPartner
+* @released
+* @since v7.0
+*/
+ {
+public:
+ /**
+ * Constructor
+ * @param aContext Packet context
+ */
+ inline RMBufHookPacket(MPacketContext *const aContext) : iContext(aContext) {}
+ inline TInt SetHookValue(const TUint32 aId, const TUint32 aValue)
+ /**
+ * Sets a (key,value) pair.
+ *
+ * If a setting already exists for the key, the value is just replaced.
+ *
+ * @param aId Key
+ * @param aValue Value associated with the key
+ * @return KErrNone, if the value was stored,
+ * @return KErrNoMemory, if there was no room to store the value
+ */
+ { return iContext->SetHookValue(aId, aValue); }
+
+ inline TInt HookValue(const TUint32 aId) const
+ /**
+ * Gets the value associated with the specified key.
+ *
+ * @param aId Key
+ * @return The value, or 0 if no value was found for the key
+ *
+ * Note: There is no way to distinquish between 'no stored value'
+ * and 'stored value = 0'.
+ */
+ { return iContext->HookValue(aId); }
+private:
+ // The packet context handler. This is always defined while the
+ // packet is being processed by the hooks.
+ MPacketContext *const iContext;
+ };
+
+//
+// MIp6Hook
+//
+class MIp6Hook : public MInetBase
+/** Abstract IP hook interface.
+*
+* A protocol which binds to the stack as a hook
+* must implement this interface.
+*
+* @warning
+* Even though this is a mixin class, all protocol hooks
+* <b>MUST</b> be derived from CIp6Hook, which includes MIp6Hook.
+* The stack assumes that all hooks use CIp6Hook derived
+* classes. This is only for hooks, an upper layer protocol
+* can be anything derived from CProtocolBase. However, the
+* recommended base class for the upper layer is CProtocolInet6Binder.
+* The recommended generic base class for any hook is CProtocolPosthook,
+* which inherits from CIp6Hook.
+*
+* An IPv6 packet can have several layers of extension headers
+* to be peeled off, before the actual transport layer is reached.
+* This process must be done by the installed hooks following this
+* API. The stack includes default hooks for the obligatory extension
+* headers (destination, hop-by-hop and routing headers). A hook which
+* implements an extension header for the protocol number N, attaches
+* itself to the stack by calling
+@code
+ NetworkService()->BindL(this, BindHookFor(N));
+@endcode
+* and starts receiving a call to the ApplyL() function for
+* each protocol header N. It is possible that one packet contains
+* multiple instances of the header N, and ApplyL is called
+* for each of them. If multiple hooks register for the same
+* protocol, they are called sequentially until any of them
+* handles the header or rejects the packet.
+*
+* A hook can also register to be called just before the packet
+* is going to be passed to the upper layer by calling:
+@code
+ NetworkService()->BindL(this, BindHookAll());
+@endcode
+* Any number of hooks can register this way and the ApplyL()
+* is called sequentially until any of them rejects the packet.
+* If all of them pass the packet, the packet goes to the
+* upper layer protocol.
+*
+* A hook can also process outgoing packets. This type of hook
+* should implement OpenL(), SetFlowOption() and GetFlowOption().
+* The outbound processing is totally different from the inbound
+* processing, and is based on the flow architecture and MFlowHook.
+* Registerning for outbound flow processing is
+@code
+ NetworkService()->BindL(this, BindFlowHook());
+@endcode
+* If a hook is interested in packets which the stack would
+* forward, if forwarding is enabled, there is a binding code
+* for that too:
+@code
+ NetworkService()->BindL(this, BindForwardHook());
+@endcode
+* The ApplyL() of the forwarding hook is called for each received
+* packet, which does not have a destination address of this node
+* (either unicast or multicast group).
+*
+* Finally, a hook can be a post processing hook, which sees raw
+* packets as they come from the network interfaces (inbound) or are
+* going out to the interface (outbound).
+* The base class for a post processing hook should be CProtocolPosthook.
+* The registering for post processing hook is:
+@code
+ NetworkService()->BindL(this, BindPostHook()); // for outbound
+ NetworkService()->BindL(this, BindPreHook()); // for inbound.
+@endcode
+*
+* All hooks can monitor which interfaces are attached to the stack.
+* This requires implementing InterfaceAttached() and InterfaceDetached().
+*
+* @publishedPartner
+* @released
+* @since v7.0
+*
+* @dontinclude mip6hook.cpp
+* Example using a hook class
+* @skip class CHookExample
+* @until //-
+* and registering hooks with the stack to handle extension header
+* in all incoming and outgoing packets:
+* @skip ::NetworkAttachedL
+* @until //-
+*/
+ {
+public:
+ inline static TUint BindHookFor(TUint8 aProtocol)
+ /**
+ * Gets the ID value for binding as an inbound hook for the
+ * specified protocol.
+ *
+ * @param aProtocol Protocol number (0..255) for which to get ID
+ * @return The ID value
+ */
+ { return KIp6Hook_ANY + aProtocol; }
+ inline static TUint BindHookAll()
+ /**
+ * Gets the ID value for binding as an inbound hook for all protocols.
+ *
+ * @return The ID value
+ */
+ { return 2*KIp6Hook_ANY; }
+ inline static TUint BindFlowHook(TUint8 aPriority = 1)
+ /**
+ * Gets the ID value for binding as an outbound flow hook
+ * with the specified priority.
+ *
+ * The priority determines the calling order for OpenL() sequence.
+ *
+ * @param aPriority Priority value (allowed range [1..255])
+ * @return The ID value
+ */
+ { return 2*KIp6Hook_ANY + Max(Min(KIp6Hook_ANY-1, aPriority), 1); }
+ inline static TUint BindPostHook()
+ /**
+ * Gets the ID value for binding as an outbound packet
+ * post-processor (below the IP layer).
+ *
+ * See CProtocolPosthook.
+ *
+ * @return The ID value
+ */
+ { return 3*KIp6Hook_ANY; }
+ inline static TUint BindPreHook()
+ /**
+ * Gets the ID value for binding as an inbound packet
+ * pre-processor (below IP layer)
+ *
+ * See CProtocolPosthook.
+ *
+ * @return The ID value
+ */
+ { return BindPostHook()+1; }
+ inline static TUint BindForwardHook()
+ /**
+ * Gets the ID value for binding as a forwarding hook
+ *
+ * @return The ID value
+ */
+ { return BindPreHook()+1; }
+ /**
+ * Processing of incoming packet.
+ *
+ * Depending on the how the hook binds to the stack, the stack calls
+ * this function from different places during the inbound packet
+ * processing path:
+ *
+ * @li
+ * to implement new (or just to monitor occurrence of) header, do a bind
+ * with BindHookFor(protocol) and the stack calls this function whenever
+ * a header of the protocol is encountered within the packet (some headers
+ * can appear more than once per packet). The RMBufRecvPacket::iProtocol
+ * contains the protocol.
+ * @li
+ * to watch all packets for upper layer protocols, do a bind with
+ * BindHookAll() and the stack calls this function for every packet
+ * about to be passed on to the upper layer protocol (identified
+ * by RMBufRecvPacket::iProtocol).
+ * @li
+ * to watch all packets which stack would forward (or drop if forwarding
+ * is disabled), do a bind with BindForwardHook(), and the stack calls
+ * this function whenever a packet would be forwarded.
+ *
+ * The same hook can request all of the above callbacks. However, then
+ * the function may have some difficulties in determining the type
+ * of call from the packet and associated information.
+ *
+ * In addition to normal packet parsing (RMBufRecvInfo::iIcmp == 0),
+ * the ApplyL is also called when processing a returned packet within
+ * the ICMP error message (RMBufRecvInfo::iIcmp != 0).
+ *
+ * The function receives the packet and information about the state of
+ * its processing.
+ *
+ * The hook has three choices of returns as follows:
+ *
+ * @li < 0:
+ * The hook dropped or passed the packet elsewhere.
+ * The main loop goes to the next packet
+ *
+ * @li #KIp6Hook_PASS (= 0):
+ * The hook has completed, and the header is still in the packet,
+ * and has possibly been modified. The main loop continues processing
+ * this header with the next hook or protocol
+ *
+ * @li #KIp6Hook_DONE (= 1):
+ * The hook has completed, the header has been handled. The
+ * hook is responsible for updating the iOffset and other fields
+ * to skip over the processed header.
+ * The main loop will restart to process the new protocol.
+ *
+ * In the case of a ICMPv6 Parameter Problem message, the value of the
+ * aInfo.iParameter is an offset to the problematic value relative to
+ * the start of the original packet. To check whether the parameter
+ * problem applies to the current header, the code must test whether
+ * the offset falls between
+@verbatim
+ 0 <= (iParameter + aInfo.iOffsetIp - aInfo.iOffset) < header_length
+@endverbatim
+ *
+ * @param aPacket
+ * The received packet. On return, the packet as modified by the hook.
+ * @param aInfo
+ * The packet information. On return, the information as modified by
+ * the hook.
+ * @return
+ * Return code, as described above.
+ * @leave error
+ * The packet is dropped and buffers are released.
+ *
+ * Example: @ref doc_example_1
+ * @dontinclude mip6hook.cpp
+ * @skip class TExtensionHeader
+ * @until //-
+ * Only this hoook knows how to handle it. The stack needs the help of this
+ * hook for normal packets, and also for processing the returned packet
+ * inside the ICMP error reports.
+ * @skip ::ApplyL
+ * @until //-
+ */
+ virtual TInt ApplyL(RMBufHookPacket &aPacket, RMBufRecvInfo &aInfo) = 0;
+
+ /**
+ * Opening a hook for a flow.
+ *
+ * The OpenL is called once at flow opening phase, if the hook has
+ * registered a flow hook using BindFlowHook() id.
+ * OpenL must decide whether the flow needs any processing by this hook.
+ * If yes, it must return with a non-NULL pointer to an instance of
+ * MFlowHook. The returned handler is attached to the flow until it
+ * closes, which event is informed to the hook by the MFlowHook::Close
+ * method.
+ *
+ * @param aHead
+ * Contains the address information of the flow.
+ * A hook can update this information in the Open phase, if required.
+ * @param aFlow The flow for which the hook is being activated
+ * @return
+ * MFlowHook pointer (!= NULL), if the hook attaches to the flow using this handler.
+ * Returning NULL means that the hook has no interest on this flow.
+ *
+ * @leave error (< 0).
+ * The flow setup is aborted and the indicated error is passed to
+ * the application.
+ * @leave EFlow_PENDING
+ * (leave with anything > 0). The flow setup is aborted and flow
+ * is treated as if no route for the destination was available
+ * (flow is put into pending state).
+ * This may activate additional interface setups.
+ *
+ * @note
+ * This function has a default implmentation, which returns NULL.
+ *
+ * Example: @ref doc_example_1
+ * Attach to every outbound flow:
+ * @dontinclude mip6hook.cpp
+ * @skip ::OpenL
+ * @until //-
+ *
+ * But, then we need to suply the MFlowHook methods as well.
+ * @skip ::ReadyL
+ * @until //-
+ *
+ * and
+ *
+ * @skip ::ApplyL
+ * @until //-
+ */
+ virtual MFlowHook *OpenL(TPacketHead &aHead, CFlowContext *aFlow)
+ {
+ (void)aHead; (void)aFlow; // silence compiler warnings
+ return NULL;
+ }
+ /**
+ * Implements additional flow options in the hook.
+ *
+ * When a hook registers for outbound packets, it will also get these calls whenever
+ * the upper layer uses the GetOption to a flow.
+ *
+ * @note
+ * This function has a default implementation, which returns KErrNotSupported.
+ * @note
+ * The flow does not need to be open when this call occurs. If hook implements
+ * any options, it should use the CFlowContext::RetrieveOption for the current
+ * value of the option.
+ *
+ * @param aLevel The option level code
+ * @param aName The option name code
+ * @retval aOption The option value (if KErrNone)
+ * @param aFlow The flow
+ * @return error code (KErrNotSupported) or KErrNone
+ *
+ * Example: @ref doc_example_1
+ * The current example port and protocol number can be read by a socket option
+ * by any application code. Assuming socket is an opened RSocket (for example,
+ * an UDP socket), then
+ *
+ * @code
+ TPckgBuf<TUint> opt;
+ RSocket socket;
+ if (socket.GetOpt(KSoHookExample_PROTOCOL, KSolHookExample, opt) == KErrNone)
+ {
+ ...
+ protocol = opt();
+ ...
+ }
+ @endcode
+ *
+ * enters the GetFlowOption function in the example hook:
+ * @dontinclude mip6hook.cpp
+ * @skip ::GetFlowOption
+ * @until //-
+ */
+ virtual TInt GetFlowOption(TUint aLevel, TUint aName, TDes8 &aOption, const CFlowContext &aFlow) const
+ {
+ (void)aLevel; (void)aName; (void)aOption; (void)aFlow; // silence compiler warnings
+ return KErrNotSupported;
+ }
+ /**
+ * Implements additional flow options in the hook.
+ *
+ * When a hook registers for outbound packets, it will also get these calls whenever
+ * the upper layer uses the SetOption to a flow.
+ *
+ * @note
+ * This function has a default implementation, which returns KErrNotSupported.
+ * @note
+ * The flow does not need to be open when this call occurs. The hook should not store
+ * the pointer of the flow. Instead, it should use the CFlowContext::StoreOption to
+ * remember the option values.
+ *
+ * @param aLevel The option level code
+ * @param aName The option name code
+ * @param aOption The option value
+ * @param aFlow The flow
+ * @return error code (KErrNotSupported) or KErrNone
+ *
+ * Example: @ref doc_example_1
+ * The example port and protocol number can be changed by a socket option.
+ * Assuming socket is an opened RSocket (for example, an UDP socket), then
+ * @code
+ TPckgBuf<TUint> opt;
+ RSocket socket;
+ opt() = 18;
+ if (socket.SetOpt(KSoHookExample_PROTOCOL, KSolHookExample, opt) == KErrNone)
+ {
+ // Succesfully changed the protocol number!
+ }
+ @endcode
+ *
+ * enters the SetFlowOption function in the example hook:
+ * @dontinclude mip6hook.cpp
+ * @skip ::SetFlowOption
+ * @until //-
+ */
+ virtual TInt SetFlowOption(TUint aLevel, TUint aName, const TDesC8 &aOption, CFlowContext &aFlow)
+ {
+ (void)aLevel; (void)aName; (void)aOption; (void)aFlow; // silence compiler warnings
+ return KErrNotSupported;
+ }
+ /**
+ * Monitoring attached interfaces.
+ *
+ * A hook can monitor what interfaces are attached
+ * to the stack by overriding the MIp6Hook::InterfaceAttached and
+ * MIp6Hook::InterfaceDetached.
+ *
+ * The InterfaceAttached is called just after the CNifIfBase
+ * pointer has been stored into the internal interface
+ * instance and CNifIfBase::Open() has been called.
+ *
+ * @note
+ * It is possible to receive InteraceDetached
+ * without a matching InterfaceAttached, because interfaces can
+ * be up before the hook is active.
+ *
+ * @param aName The name of the interface within the stack
+ * @param aIf The interface
+ */
+ virtual void InterfaceAttached(const TDesC &aName, CNifIfBase *aIf) {(void)aName; (void)aIf;}
+ /**
+ * Monitoring attached interfaces.
+ *
+ * A hook can monitor what interfaces are attached
+ * to the stack by overriding the MIp6Hook::InterfaceAttached and
+ * MIp6Hook::InterfaceDetached.
+ *
+ * The InterfaceDetached is called just before the CNifIfBase
+ * pointer is going to be removed from the internal interface
+ * instance and before calling the CNifIfBase::Close().
+ *
+ * @note
+ * It is possible to receive InteraceDetached
+ * without a matching InterfaceAttached, because interfaces can
+ * be up before the hook is active.
+ *
+ * @param aName The name of the interface within the stack
+ * @param aIf The interface
+ */
+ virtual void InterfaceDetached(const TDesC & aName, CNifIfBase *aIf) {(void)aName; (void)aIf;}
+ };
+
+
+
+class CIp6Hook: public CProtocolBaseUnbind, public MIp6Hook
+/**
+* The base class of all hook protocols.
+*
+* See MIp6Hook and CProtocolBaseUnbind.
+*
+* @publishedPartner
+* @released
+* @since v7.0
+*/
+ {
+public:
+ /**
+ * Processes an incoming packet.
+ *
+ * @see MIp6Hook::ApplyL().
+ * @param aPacket Packet to process
+ * @param aInfo Packet information
+ * @return System-wide error code
+ */
+ virtual TInt ApplyL(RMBufHookPacket &aPacket, RMBufRecvInfo &aInfo) = 0;
+
+public:
+ //
+ // Silence compiler
+ //
+ /**
+ * dummy
+ */
+ void Identify(struct TServerProtocolDesc *) const {} // should put something here!!
+ /**
+ * The inbound hooks don't need this really
+ */
+ void Unbind(CProtocolBase *, TUint) {} // The inbound hooks don't need this really.
+ };
+
+#endif