aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/interceptor/interceptor.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/interceptor/interceptor.h')
-rw-r--r--drivers/interceptor/interceptor.h720
1 files changed, 720 insertions, 0 deletions
diff --git a/drivers/interceptor/interceptor.h b/drivers/interceptor/interceptor.h
new file mode 100644
index 0000000..054daf1
--- /dev/null
+++ b/drivers/interceptor/interceptor.h
@@ -0,0 +1,720 @@
+/* Netfilter Driver for IPSec VPN Client
+ *
+ * Copyright(c) 2012 Samsung Electronics
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * interceptor.h
+ *
+ * Interceptor API specifies the Interceptor side interface between
+ * the Interceptor and Engine components. This API contains functions
+ * for Interceptor initialization, packet allocation, packet data access,
+ * routing and packet sending.
+ *
+ */
+
+#ifndef INTERCEPTOR_H
+#define INTERCEPTOR_H
+
+#include "sshinet.h"
+
+/** The amount of space to reserve in packet header for the IPsec engine. */
+#define SSH_INTERCEPTOR_UPPER_DATA_SIZE 192
+
+/** The number of available extension selectors for platform-specific
+ extensions. */
+#define SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS 1
+
+/** Size of interface system name. */
+#define SSH_INTERCEPTOR_IFNAME_SIZE 64
+
+/** Data type for the interceptor context. */
+typedef struct SshInterceptorRec *SshInterceptor;
+
+/** This type defines the type of a network interface interface. The
+ type is supposed to be sufficient to determine how to process the
+ packets. It is not expected to provide maximal detail to the
+ user. Regardless of the interface type, the higher-level code
+ should not assume that incoming packets have been defragmented,
+ nor will it assume that the interceptor will perform fragmentation
+ for outgoing packets. Thus, it will perform these functions
+ itself. It will not assume the underlying interceptor will do it.
+ Routing will also be done by the higher level to determine which
+ interface a packet should go out from. */
+typedef enum {
+ SSH_INTERCEPTOR_MEDIA_NONEXISTENT, /** The interface is not available */
+ SSH_INTERCEPTOR_MEDIA_PLAIN, /** Any interceptor w/o media headers*/
+ SSH_INTERCEPTOR_MEDIA_ETHERNET, /** Ethernet (rfc894) framing */
+ SSH_INTERCEPTOR_MEDIA_FDDI, /** FDDI (rfc1042/rfc1103) framing */
+ SSH_INTERCEPTOR_MEDIA_TOKENRING, /** Tokenring (rfc1042/rfc1469) framing */
+ /** New types may be added here. Look for one of the existing types
+ to find all places in code that should be updated. */
+ SSH_INTERCEPTOR_NUM_MEDIAS /** Must be the last entry! */
+} SshInterceptorMedia;
+
+/** Protocol identifiers. These identify recognized protocols (packet
+ formats) in a portable manner. This enumeration includes media
+ types, but also all recognized higher-level protocols. */
+typedef enum
+{
+ SSH_PROTOCOL_IP4, /** IPv4 frame */
+ SSH_PROTOCOL_IP6, /** IPv6 frame */
+ SSH_PROTOCOL_IPX, /** IPX frame */
+ SSH_PROTOCOL_ETHERNET, /** Ethernet frame */
+ SSH_PROTOCOL_FDDI, /** FDDI frame */
+ SSH_PROTOCOL_TOKENRING, /** Token Ring frame */
+ SSH_PROTOCOL_ARP, /** ARP frame */
+ SSH_PROTOCOL_OTHER, /** some other type frame */
+ SSH_PROTOCOL_NUM_PROTOCOLS /** must be the last entry! */
+} SshInterceptorProtocol;
+
+/** Data type for an interface number. This type must be atleast as big as
+ the system interface index. */
+typedef SshUInt32 SshInterceptorIfnum;
+
+/** Maximum value of interface number.
+ All valid interface numbers must be smaller than this value. */
+#define SSH_INTERCEPTOR_MAX_IFNUM ((SshInterceptorIfnum) 0xffffffff)
+
+/** Reserved value for invalid interface number. */
+#define SSH_INTERCEPTOR_INVALID_IFNUM SSH_INTERCEPTOR_MAX_IFNUM
+
+/** Data structure for representing an address for a network interface. */
+typedef struct SshInterfaceAddressRec
+{
+ /** Protocol for which the address is. */
+ SshInterceptorProtocol protocol;
+
+ /** The address itself. */
+ union
+ {
+ /** IPv4 and IPv6. */
+ struct
+ {
+ SshIpAddrStruct ip;
+ SshIpAddrStruct mask;
+ SshIpAddrStruct broadcast;
+ } ip;
+
+ /** IPX */
+ struct
+ {
+ SshUInt32 net;
+ unsigned char host[6];
+ } ns;
+ } addr;
+} *SshInterfaceAddress, SshInterfaceAddressStruct;
+
+/** Flags for the media direction information. */
+
+/** Do not fragment before sending from engine. */
+#define SSH_INTERCEPTOR_MEDIA_INFO_NO_FRAGMENT 0x0001
+
+/** Accessor for mtu member in SshInterceptorMediaDirectionInfo. */
+#ifdef WITH_IPV6
+#define SSH_INTERCEPTOR_MEDIA_INFO_MTU(info, is_ipv6) \
+ ((is_ipv6) ? (info)->mtu_ipv6 : (info)->mtu_ipv4)
+#else /* WITH_IPV6 */
+#define SSH_INTERCEPTOR_MEDIA_INFO_MTU(info, is_ipv6) \
+ ((info)->mtu_ipv4)
+#endif /* WITH_IPV6 */
+
+/** Media direction information. This information is used when engine
+ is sending packets to the interceptor. */
+typedef struct SshInterceptorMediaDirectionInfoRec
+{
+ SshInterceptorMedia media; /* media type */
+ SshUInt32 flags; /* flags */
+ size_t mtu_ipv4; /* mtu for the direction (ipv4) */
+#ifdef WITH_IPV6
+ size_t mtu_ipv6; /* mtu for the direction (ipv6) */
+#endif /* WITH_IPV6 */
+} *SshInterceptorMediaDirectionInfo, SshInterceptorMediaDirectionInfoStruct;
+
+/** Flag values for flags in SshInterceptorInterface */
+/* Interface type */
+#define SSH_INTERFACE_FLAG_VIP 0x0001
+#define SSH_INTERFACE_FLAG_POINTOPOINT 0x0002
+#define SSH_INTERFACE_FLAG_BROADCAST 0x0004
+/* Interface link status */
+#define SSH_INTERFACE_FLAG_LINK_DOWN 0x0100
+
+/** Data structure for providing information about a network
+ interface. */
+typedef struct
+{
+ SshInterceptorMediaDirectionInfoStruct to_protocol;
+ SshInterceptorMediaDirectionInfoStruct to_adapter;
+ char name[SSH_INTERCEPTOR_IFNAME_SIZE]; /** system name for the interface */
+ SshInterceptorIfnum ifnum; /** Interface number */
+ SshUInt32 num_addrs; /** Number of addresses for the interface. */
+ SshInterfaceAddress addrs; /** mallocated array of address structures. */
+ unsigned char media_addr[16]; /** MAC address, medium size and format */
+ size_t media_addr_len; /** Length of the MAC address. */
+
+ SshUInt32 flags; /** Flags for the interface. */
+
+ /** Context pointer for owner/user for this SshInterceptorInterface.
+ Can be used for e.g. storing interface-specific
+ NAT-configuration. */
+ void *ctx_user;
+} SshInterceptorInterface;
+
+/* Packet flag bits. */
+#define SSH_PACKET_FROMPROTOCOL 0x00000001U /** Packet from the protocol. */
+#define SSH_PACKET_FROMADAPTER 0x00000002U /** Packet from the adapter. */
+#define SSH_PACKET_IP4HDRCKSUMOK 0x00000004U /** IPv4 header cksum checked. */
+#define SSH_PACKET_FORWARDED 0x00000008U /** Packet was forwarded. */
+#define SSH_PACKET_HWCKSUM 0x00000010U /** TCP/UDP cksum done by NIC. */
+#define SSH_PACKET_MEDIABCAST 0x00000020U /** Packet was media broadcast. */
+#define SSH_PACKET_UNMODIFIED 0x00000200U /** Unmodified packet. */
+
+/* This flag specifies that the engine is allowed to fragment the packet if
+ the packet is too large to fit into interafce MTU. Some operating
+ system handle the fragmentation after us and therefore this flag
+ may be set for some outbound data packets. The packet is guaranteed
+ to have been originated from local stack and stack has indicated
+ that this packet can be fragmented. */
+#define SSH_PACKET_FRAGMENTATION_ALLOWED 0x00000400U
+
+/* Flag bits with mask 0x00000fff are reserved for interceptor. */
+/* Flag bits with mask 0xfffff000 are reserved for IPSEC engine. */
+
+/** Macro to access upper-level data in the packet header. */
+#define SSH_INTERCEPTOR_PACKET_DATA(packet, type) \
+ ((type)(&(packet)->upper_data))
+
+/** Data structure for a packet. These data structures can only be
+ allocated by the interceptor; higher-level code must never
+ directly allocate these (the interceptor implementation may
+ actually use a larger structure containing this public
+ structure). */
+typedef struct SshInterceptorPacketRec
+{
+ /** Flags for the packet. The SSH_PACKET_* bitmasks are used. Code
+ above the interceptor is not allowed to modify flags 0x001-0x800;
+ they may be used internally by the interceptor to pass
+ information from packet_cb/ssh_interceptor_packet_alloc to
+ ssh_interceptor_send/ssh_interceptor_packet_free. During
+ certain times, such when applying asynchronous IPSEC
+ transformations, this field may be changed concurrently by
+ another thread (or interrupt) even when another thread is
+ processing the packet. Care should be taken with locking in
+ those situations. */
+ SshUInt32 flags;
+
+ /** Number of the interface that this packet arrived from */
+ SshInterceptorIfnum ifnum_in;
+
+ /** Number of the interface that this packet going out */
+ SshInterceptorIfnum ifnum_out;
+
+ /** Format of the packet (protocol identifier). */
+ SshInterceptorProtocol protocol;
+
+ /** Path MTU stored for this packet, which must be respected at
+ media send (if interface MTU is smaller than this value, then
+ the media send routine must send ICMP PMTU message and discard
+ the packet). If 0, means use the interface MTU only. */
+ SshUInt32 pmtu;
+
+#if (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0)
+ /** Platform-dependent extension selectors for things like user id,
+ virtual network identifier, etc. */
+ SshUInt32 extension[SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS];
+#endif /* (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0) */
+
+#ifdef SSH_IPSEC_IP_ONLY_INTERCEPTOR
+ /** Route key selector that was used in the route lookup */
+ SshUInt16 route_selector;
+#endif /* SSH_IPSEC_IP_ONLY_INTERCEPTOR */
+
+ /** Buffer that can be used by higher level software to store its
+ data (such as cached media addresses). This field can only be
+ accessed using the SSH_INTERCEPTOR_PACKET_DATA macro. */
+ union {
+ /** Contents of this union are private (they are there to
+ guarantee proper alignment for any data structure stored
+ here). */
+ long force_alignment_l; int force_alignment_i; short force_alignment_s;
+ void *force_alignment_v;
+ SshUInt16 force_alignment_i16; SshUInt32 force_alignment_i32;
+ SshUInt64 force_alignment_i64;
+ char force_size_dont_use_this_directly[SSH_INTERCEPTOR_UPPER_DATA_SIZE];
+ /* Should have double here if floating point was allowed. */
+ } upper_data;
+
+ /** Next pointer on freelist. This can also be used by higher-level
+ code to put the packet on a list. */
+ struct SshInterceptorPacketRec *next;
+} *SshInterceptorPacket, SshInterceptorPacketStruct;
+
+/** Error codes for route add / remove functions. */
+typedef enum {
+ SSH_INTERCEPTOR_ROUTE_ERROR_OK = 0,
+ SSH_INTERCEPTOR_ROUTE_ERROR_NONEXISTENT = 1,
+ SSH_INTERCEPTOR_ROUTE_ERROR_OUT_OF_MEMORY = 2,
+ SSH_INTERCEPTOR_ROUTE_ERROR_ALREADY_EXISTS = 3,
+ SSH_INTERCEPTOR_ROUTE_ERROR_UNDEFINED = 255
+} SshInterceptorRouteError;
+
+/** Flag values for the route add / remove functions. */
+
+/** Ignore non-existent routes when attempting to remove the route. */
+#define SSH_INTERCEPTOR_ROUTE_FLAG_IGNORE_NONEXISTENT 0x0001
+
+/** Data structure for routing key, used in route lookups and routing table
+ manipulation.
+
+ The route lookup is performed for the destination address, using other
+ fields in the routing key to enforce routing policies. It is a fatal
+ error to call ssh_interceptor_route using a SshInterceptorRouteKey
+ which does not have the destination address set.
+
+ Use the provided macros for setting fields in SshInterceptorRouteKey.
+
+ Note that on platforms that do not support policy routing, the route lookup
+ uses only the destination address. On other platforms other fields of the
+ SshInterceptorRouteKey may be used in the route lookup. */
+typedef struct SshInterceptorRouteKeyRec
+{
+ /** Destination address, mandatory */
+ SshIpAddrStruct dst;
+ /** Source address, optional */
+ SshIpAddrStruct src;
+ /** IP protocol identifier, optional */
+ SshUInt32 ipproto;
+ /** Interface number, optional.
+ Note that this field specifies either the inbound interface number
+ or the outbound interface number, depending on the value of the
+ 'selector' field. */
+ SshUInt32 ifnum;
+ /** Network layer fields */
+ union
+ {
+ /** IPv4 TOS, optional */
+ struct
+ {
+ SshUInt8 tos;
+ } ip4;
+ /** IPv6 priority and flow label, optional */
+ struct
+ {
+ SshUInt8 priority;
+ SshUInt32 flow;
+ } ip6;
+ /** For encoding / decoding */
+ unsigned char raw[5];
+ } nh;
+ /** Transport layer fields */
+ union
+ {
+ /** TCP / UDP ports, optional */
+ struct
+ {
+ SshUInt16 dst_port;
+ SshUInt16 src_port;
+ } tcp;
+ /** ICMP type and code, optional */
+ struct
+ {
+ SshUInt8 type;
+ SshUInt8 code;
+ } icmp;
+ /** ESP / AH spi, optional */
+ struct
+ {
+ SshUInt32 spi;
+ } ipsec;
+ /** For encoding / decoding */
+ unsigned char raw[4];
+ } th;
+#if (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0)
+ /** Platform-dependent extension selectors, optional */
+ SshUInt32 extension[SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS];
+#endif /* (SSH_INTERCEPTOR_NUM_EXTENSION_SELECTORS > 0) */
+ /** Bitmap of selectors that are to be used in the route lookup.
+ Use the provided macros to add selectors to the routing key,
+ do not access this field directly. The highest 3 bits of
+ 'selector' are reserved for flags defined below. */
+ SshUInt16 selector;
+} *SshInterceptorRouteKey, SshInterceptorRouteKeyStruct;
+
+/* Selector values for 'selector' bitmap */
+
+/** Source address */
+#define SSH_INTERCEPTOR_ROUTE_KEY_SRC 0x0001
+/** IP protocol identifier */
+#define SSH_INTERCEPTOR_ROUTE_KEY_IPPROTO 0x0002
+/** Inbound interface number */
+#define SSH_INTERCEPTOR_ROUTE_KEY_IN_IFNUM 0x0004
+/** Outbound interface number */
+#define SSH_INTERCEPTOR_ROUTE_KEY_OUT_IFNUM 0x0008
+/** IPv4 type of service */
+#define SSH_INTERCEPTOR_ROUTE_KEY_IP4_TOS 0x0010
+/** Platform-dependent Extension selectors */
+#define SSH_INTERCEPTOR_ROUTE_KEY_EXTENSION 0x1000
+
+/* Flag values for 'selector' bitmap */
+
+/** Packets going to this destination are transformed by the engine and the
+ resulting packet may be larger than the path MTU reported to the IP stack
+ by the engine. */
+#define SSH_INTERCEPTOR_ROUTE_KEY_FLAG_TRANSFORM_APPLIED 0x2000
+/** Source address belongs to one of the local interfaces. */
+#define SSH_INTERCEPTOR_ROUTE_KEY_FLAG_LOCAL_SRC 0x4000
+
+/** A callback function of this type will be called when the
+ interceptor is first opened, and from then on whenever there is a
+ change in the interface list (e.g., a new interface goes up or
+ down or the address of an interface changes). This function will
+ be given a list of the interfaces. The supplied array will only
+ be valid for the duration of this call; the implementation of this
+ function is supposed to copy the information if it is going to
+ need it later. Note that this function may be called
+ asynchronously, concurrently with any other functions. */
+typedef void (*SshInterceptorInterfacesCB)(SshUInt32 num_interfaces,
+ SshInterceptorInterface *ifs,
+ void *context);
+
+/** Callback functions of this type are called whenever a packet is
+ received from the network or from a protocol. This function must
+ eventually free the packet, either by calling
+ ssh_interceptor_packet_free on the packet or by passing it to the
+ ssh_interceptor_send function. Note that this function may be
+ called asynchronously, concurrently with any other functions.
+
+ When a packet is passed to this callback, the `pp->flags' field
+ may contain arbitrary flags in the bits reserved for the
+ interceptor (mask 0x00000fff). This callback is not allowed to
+ modify any of those bits; they must be passed intact to
+ ssh_interceptor_send or ssh_interceptor_packet_free. Any other
+ bits (mask 0xfffff000) will be zero when the packet is sent to
+ this callback; those bits may be used freely by this callback.
+ They are not used by the interceptor. */
+typedef void (*SshInterceptorPacketCB)(SshInterceptorPacket pp, void *context);
+
+/** A callback function of this type is used to notify code above the
+ interceptor that routing information has changed, and any cached
+ routing data should be thrown away and refreshed by a new route
+ lookup. */
+typedef void (*SshInterceptorRouteChangeCB)(void *context);
+
+/** Opens the packet interceptor. This must be called before using
+ any other interceptor functions. This registers the callbacks
+ that the interceptor will use to notify the higher levels of
+ received packets or changes in the interface list. The interface
+ callback will be called once either during this call or soon after
+ this has returned.
+
+ The `machine_context' argument is intended to be meaningful only
+ to machine-specific code. It is passed through from the
+ machine-specific main program. One example of its possible uses
+ is to identify a virtual router in systems that implement multiple
+ virtual routers in a single software environment. Most
+ implementations will ignore this argument.
+
+ The `packet_cb' callback will be called whenever a packet is
+ received from either a network adapter or a protocol stack. The
+ first calls may arrive already before this function has returned.
+
+ The `interfaces_cb' callback will be called once soon after
+ opening the interceptor (possibly before this call returns). From
+ then on, it will be called whenever there is a change in the
+ interface list (e.g., the IP address of an interface is changed,
+ or a PPP interface goes up or down).
+
+ The `route_change_cb' callback should be called whenever there is
+ a change in routing information. Implementing this callback is
+ optional but beneficial in e.g. router environments (the
+ information is not easily available on all systems).
+
+ The `context' argument is passed to the callbacks.
+
+ This function returns TRUE if opening the interceptor was
+ successful. The interceptor object is returned in the
+ `interceptor_return' argument. Most systems will only allow a
+ single interceptor to be opened; however, some systems may support
+ multiple interceptors identified by the `machine_context'
+ argument. This returns FALSE if an error occurs (e.g., no
+ interceptor kernel module is loaded on this system, or the
+ interceptor is already open).
+
+ Care must be taken regarding concurrency control in systems that have
+ multithreaded IP stacks. In particular:
+ - packet_cb and interfaces_cb may get called before this function
+ returns. It is, however, guaranteed that `*interceptor_return'
+ has been set before the first call to either of them.
+ - the interceptor cannot be closed while there are calls or packets
+ out. The ssh_interceptor_stop function must be used.
+ In such systems, additional concurrency may be introduced by timeouts
+ and actions from the policy manager connection. */
+Boolean ssh_interceptor_open(void *machine_context,
+ SshInterceptorPacketCB packet_cb,
+ SshInterceptorInterfacesCB interfaces_cb,
+ SshInterceptorRouteChangeCB route_change_cb,
+ void *context,
+ SshInterceptor *interceptor_return);
+
+/** Sends a packet to the network or to the protocol stacks. This
+ will eventually free the packet by calling
+ ssh_interceptor_packet_free. The `media_header_len' argument
+ specifies how many bytes from the start of the packet are media
+ (link-level) headers. It will be 0 if the interceptor operates
+ directly at protocol level. If the configure define
+ INTERCEPTOR_IP_ALIGNS_PACKETS is set, this function must ensure
+ that the IP header of the packet is aligned to a word boundary.
+
+ This function relies on 'pp->ifnum_out' being an 'ifnum' which has
+ previously been reported via a SshInterceptorInterfacesCB. It does
+ not have to be valid at that precise point in time. If 'pp->ifnum_out'
+ is an ifnum which may have been previously reported to the
+ SshInterceptorInterfacesCB, then ssh_interceptor_send() MUST check
+ that it is valid, or otherwise discard the packet. Also,
+ pp->protocol (and the corresponding encapsulation) may be
+ incorrect for the interface denoted by 'pp->ifnum_out'. The packet
+ should be dropped also in this case.
+
+ This function can be called concurrently from multiple threads,
+ but only for one packet at a time. It is ok to call this even
+ before ssh_interceptor_open has actually returned (from a
+ `packet_cb' or `interface_cb' callback). */
+
+void ssh_interceptor_send(SshInterceptor interceptor,
+ SshInterceptorPacket pp,
+ size_t media_header_len);
+
+/** Enables or disables packet interception. */
+void ssh_interceptor_enable_interception(SshInterceptor interceptor,
+ Boolean enable);
+
+/** Stops the packet interceptor. After this call has returned, no
+ new calls to the packet and interfaces callbacks will be made.
+ The interceptor keeps track of how many threads are processing
+ packet, interface, or have pending route callbacks, and this
+ function returns TRUE if there are no callbacks/pending calls to
+ those functions. This returns FALSE if threads are still
+ executing in those callbacks or routing callbacks are pending.
+
+ After calling this function, the higher-level code should wait for
+ packet processing to continue, free all packet structures received
+ from that interceptor, and then call ssh_interceptor_close. It is
+ not an error to call this multiple times (the latter calls are
+ ignored).
+
+ It is forbidden to hold ANY locks when calling
+ ssh_interceptor_stop(). */
+
+Boolean ssh_interceptor_stop(SshInterceptor interceptor);
+
+/** Closes the packet interceptor. This function can only be called when
+ - ssh_interceptor_stop has been called
+ - all packet and interface callbacks from this interceptor have
+ returned.
+ - all ssh_interceptor_route completions have been called
+ - all packets received from the packet callbacks from this interceptor
+ have been freed.
+
+ It is illegal to call any packet interceptor functions (other than
+ ssh_interceptor_open) after this call. This function cannot be
+ called from an interceptor callback.
+
+ This function can be called from one thread only for any particular
+ interceptor. If multiple interceptors are supported, then this may be
+ called for different interceptors asynchronously. */
+void ssh_interceptor_close(SshInterceptor interceptor);
+
+/** Completion function for route lookup. This function is called when the
+ route lookup is complete.
+ reachable FALSE if the destination cannot be reached, TRUE otherwise
+ next_hop_gw IP address of next hop gw or destination
+ ifnum network interface to which to send the packet
+ mtu path mtu, or 0 if not known (= should use link mtu)
+ context context argument supplied to route request.
+
+ This function may get called concurrently from multiple threads. */
+typedef void (*SshInterceptorRouteCompletion)(Boolean reachable,
+ SshIpAddr next_hop_gw,
+ SshInterceptorIfnum ifnum,
+ size_t mtu,
+ void *context);
+
+/** Looks up routing information for the routing key specified
+ by `key'. Calls the callback function either during this
+ call or some time later. The purpose of the callback function is
+ to allow this function to perform asynchronous operations, such as
+ forwarding the routing request to a user-level process. This
+ function will not be very efficient on some systems, and calling
+ this on a per-packet basis should be avoided if possible.
+ This function expects that 'key' is valid only for the duration
+ of the call, and will take a local copy of it, if necessary.
+
+ Note that if this function is implemented by forwarding the
+ request to a user-level process, care must be taken to never lose
+ replies. The completion function must *always* be called. For
+ example, if the policy manager interface is used to pass the
+ requests to the policy manager process, and the interface is
+ closed, the completion function must still be called for all
+ requests. Code may be needed to keep track of which requests are
+ waiting for replies from the user-level process.
+
+ This function can be called concurrently from multiple threads.
+ While legal, new calls to this function after calling
+ ssh_interceptor_stop should be avoided, because it is not possible
+ to call ssh_interceptor_close until all route lookup completions
+ have been called. */
+void ssh_interceptor_route(SshInterceptor interceptor,
+ SshInterceptorRouteKey key,
+ SshInterceptorRouteCompletion completion,
+ void *context);
+
+/** Allocates a packet of at least the given size. Packets can only
+ be allocated using this function (either internally by the
+ interceptor or by other code by calling this function).
+ Typically, this takes a packet header from a free list, stores a
+ pointer to a platform-specific packet object, and returns the
+ packet header. This should be re-entrant and support concurrent
+ operations if the IPSEC engine is re-entrant on the target
+ platform. Other functions in this interface should be re-entrant
+ for different packet objects, but only one operation will be in
+ progress at any given time for a single packet object. This
+ returns NULL if no more packets can be allocated. On systems that
+ support concurrency, this can be called from multiple threads
+ concurrently.
+
+ This sets initial values for the mandatory fields of the packet
+ that always need to be initialized. However, any of these fields
+ can be modified later. */
+SshInterceptorPacket ssh_interceptor_packet_alloc(SshInterceptor interceptor,
+ SshUInt32 flags,
+ SshInterceptorProtocol proto,
+ SshInterceptorIfnum ifnum_in,
+ SshInterceptorIfnum ifnum_out,
+ size_t total_len);
+
+
+/** Frees the packet.
+
+ All packets allocated by ssh_interceptor_packet_alloc must
+ eventually be freed using this function by either calling this
+ explicitly or by passing the packet to the ssh_interceptor_send
+ function. Typically, this calls a suitable function to
+ free/release the platform-specific packet object, and puts the
+ packet header on a free list. This function should be re-entrant,
+ so if a free list is used, it should be protected by a lock in
+ systems that implement concurrency in the IPSEC Engine. Multiple
+ threads may call this function concurrently for different packets,
+ but not for the same packet. */
+void ssh_interceptor_packet_free(SshInterceptorPacket pp);
+
+/** Returns the total length of the packet in bytes. Multiple threads may
+ call this function concurrently, but not for the same packet. */
+size_t ssh_interceptor_packet_len(SshInterceptorPacket pp);
+
+
+/** Copies data into the packet. Space for the new data must already
+ have been allocated. It is a fatal error to attempt to copy beyond
+ the allocated packet. Multiple threads may call this function
+ concurrently, but not for the same packet. Returns TRUE if
+ successfull and FALSE otherwise. If error occurs then the pp is
+ already freed by this function, and the caller must not refer to
+ it anymore.
+
+ There is a generic version of this function inside the engine, in
+ case interceptor does not want to implement this. If interceptor
+ implements this function it must define the
+ INTERCEPTOR_HAS_PACKET_COPYIN pre-processor symbol. */
+Boolean ssh_interceptor_packet_copyin(SshInterceptorPacket pp, size_t offset,
+ const unsigned char *buf, size_t len);
+
+/** Copies data out from the packet. Space for the new data must
+ already have been allocated. It is a fatal error to attempt to
+ copy beyond the allocated packet. Multiple threads may call this
+ function concurrently, but not for the same packet.
+
+ There is a generic version of this function inside the engine, in
+ case interceptor does not want to implement this. If interceptor
+ implements this function it must define the
+ INTERCEPTOR_HAS_PACKET_COPYOUT pre-processor symbol. */
+void ssh_interceptor_packet_copyout(SshInterceptorPacket pp, size_t offset,
+ unsigned char *buf, size_t len);
+
+
+/** These two routines provide way to export and import
+ interceptor-specific internal packet data as an opaque binary data
+ block.
+
+ If the export routine returns FALSE, the packet `pp' is
+ invalidated. If it returnes TRUE, but *data_ret is NULL, then no
+ internal data was exported. If *data_ret is non-NULL, then
+ *len_return contains the length of *data_ret in bytes. The caller
+ must free the *data_ret value using ssh_free.
+
+ The import routine returns TRUE if the data was imported
+ successfully, otherwise it returns FALSE and the packet `pp' is
+ invalidated. It is a fatal error to call import routine on the
+ same packet more than once.
+
+ Notice: If the interceptor does not define these routines, then
+ the engine provides dummy versions.
+
+ Notice: This routine overlaps a bit with
+ ssh_interceptor_packet_alloc_and_copy_ext_data, as it could be
+ implemented as:
+
+ new_pp = ssh_interceptor_packet_alloc(...);
+ ssh_interceptor_packet_copy(pp, 0, ..., new_pp, 0);
+ ssh_interceptor_packet_export_internal_data(pp, &data, &len);
+ ssh_interceptor_packet_import_internal_data(new_pp, data, len);
+ ssh_free(data);
+
+ The main purpose of these routines is to allow some per-packet
+ interceptor-specific data to be transported to the usermode
+ engine. Under the kernel IPSec Engine, these routines are not
+ actually used at all. */
+Boolean ssh_interceptor_packet_export_internal_data(SshInterceptorPacket pp,
+ unsigned char **data_ret,
+ size_t *len_return);
+
+Boolean ssh_interceptor_packet_import_internal_data(SshInterceptorPacket pp,
+ const unsigned char *data,
+ size_t len);
+
+void ssh_interceptor_packet_discard_internal_data(unsigned char *data,
+ size_t data_len);
+
+
+/** Copy data from one packet to another. Start from the
+ `source_offset' and copy `bytes_to_copy' bytes to
+ `destination_offset' in the destination packet. If the destination
+ packet cannot be written then return FALSE, and the destination
+ packet has been freed by this function. The source packet is not
+ freed even in case of error. If data copying was successfull then
+ return TRUE.
+
+ This function can also be implemented so that it will simply
+ increment the reference counts in the source packet and share the
+ actual data without copying it at all. There is a generic version
+ of this function inside the engine, in case interceptor does not
+ want to implement this. If interceptor implements this function it
+ must define INTERCEPTOR_HAS_PACKET_COPY pre-processor symbol. */
+Boolean ssh_interceptor_packet_copy(SshInterceptorPacket source_pp,
+ size_t source_offset,
+ size_t bytes_to_copy,
+ SshInterceptorPacket destination_pp,
+ size_t destination_offset);
+
+#ifdef DEBUG_LIGHT
+#define KERNEL_INTERCEPTOR_USE_FUNCTIONS
+#endif /* DEBUG_LIGHT */
+
+#ifdef INTERCEPTOR_HAS_PLATFORM_INCLUDE
+#include "platform_interceptor.h"
+#endif /* INTERCEPTOR_HAS_PLATFORM_INCLUDE */
+
+#endif /* INTERCEPTOR_H */