diff options
Diffstat (limited to 'drivers/interceptor/interceptor.h')
-rw-r--r-- | drivers/interceptor/interceptor.h | 720 |
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 */ |