summaryrefslogtreecommitdiffstats
path: root/fragment.h
diff options
context:
space:
mode:
authorDavid Sommerseth <dazo@users.sourceforge.net>2011-07-28 23:27:58 +0200
committerDavid Sommerseth <dazo@users.sourceforge.net>2011-07-28 23:27:58 +0200
commit15bd346ca01806bea3f697bbc93a979e4b4035f1 (patch)
tree35e8b3dbef7d0ce1975952fca8c17c174a2b2250 /fragment.h
parent5959e9def62659c93d023a8247e1001c8a73de9d (diff)
downloadopenvpn-15bd346ca01806bea3f697bbc93a979e4b4035f1.tar.gz
openvpn-15bd346ca01806bea3f697bbc93a979e4b4035f1.tar.xz
openvpn-15bd346ca01806bea3f697bbc93a979e4b4035f1.zip
Added data channel fragmentation docs
Signed-off-by: Adriaan de Jong <dejong@fox-it.com> Acked-by: James Yonan <james@openvpn.net> Signed-off-by: David Sommerseth <dazo@users.sourceforge.net>
Diffstat (limited to 'fragment.h')
-rw-r--r--fragment.h437
1 files changed, 364 insertions, 73 deletions
diff --git a/fragment.h b/fragment.h
index fc2b1b8..866573b 100644
--- a/fragment.h
+++ b/fragment.h
@@ -25,8 +25,20 @@
#ifndef FRAGMENT_H
#define FRAGMENT_H
+/**
+ * @file
+ * Data Channel Fragmentation module header file.
+ */
+
+
#ifdef ENABLE_FRAGMENT
+/**
+ * @addtogroup fragmentation
+ * @{
+ */
+
+
#include "common.h"
#include "buffer.h"
#include "interval.h"
@@ -34,143 +46,422 @@
#include "shaper.h"
#include "error.h"
-#define N_FRAG_BUF 25 /* number of packet buffers */
-#define FRAG_TTL_SEC 10 /* number of seconds time-to-live for a fragment */
-#define FRAG_WAKEUP_INTERVAL 5 /* wakeup code called once per n seconds */
+#define N_FRAG_BUF 25
+ /**< Number of packet buffers for
+ * reassembling incoming fragmented
+ * packets. */
+
+#define FRAG_TTL_SEC 10
+ /**< Time-to-live in seconds for a %fragment. */
+
+#define FRAG_WAKEUP_INTERVAL 5
+ /**< Interval in seconds between calls to
+ * wakeup code. */
+
+/**************************************************************************/
+/**
+ * Structure for reassembling one incoming fragmented packet.
+ */
struct fragment {
- bool defined;
+ bool defined; /**< Whether reassembly is currently
+ * taking place in this structure. */
- int max_frag_size; /* maximum size of each fragment */
+ int max_frag_size; /**< Maximum size of each %fragment. */
- /*
- * 32 bit array corresponding to each fragment. A 1 bit in element n means that
- * the fragment n has been received. Needs to have at least MAX_FRAGS bits.
- */
# define FRAG_MAP_MASK 0xFFFFFFFF
-# define MAX_FRAGS 32 /* maximum number of fragments per packet */
+ /**< Mask for reassembly map. */
+# define MAX_FRAGS 32 /**< Maximum number of fragments per packet. */
unsigned int map;
-
- time_t timestamp; /* timestamp for time-to-live purposes */
-
- struct buffer buf; /* fragment assembly buffer for received datagrams */
+ /**< Reassembly map for recording which
+ * fragments have been received.
+ *
+ * A bit array where each bit
+ * corresponds to a %fragment. A 1 bit
+ * in element n means that the %fragment
+ * n has been received. Needs to have
+ * at least \c MAX_FRAGS bits. */
+
+ time_t timestamp; /**< Timestamp for time-to-live purposes. */
+
+ struct buffer buf; /**< Buffer in which received datagrams
+ * are reassembled. */
};
+
+/**
+ * List of fragment structures for reassembling multiple incoming packets
+ * concurrently.
+ */
struct fragment_list {
- int seq_id;
- int index;
+ int seq_id; /**< Highest fragmentation sequence ID of
+ * the packets currently being
+ * reassembled. */
+ int index; /**< Index of the packet being reassembled
+ * with the highest fragmentation
+ * sequence ID into the \c
+ * fragment_list.fragments array. */
+
+/** Array of reassembly structures, each can contain one whole packet.
+ *
+ * The fragmentation sequence IDs of the packets being reassembled in
+ * this array are linearly increasing. \c
+ * fragment_list.fragments[fragment_list.index] has an ID of \c
+ * fragment_list.seq_id. This means that one of these \c fragment_list
+ * structures can at any one time contain at most packets with the
+ * fragmentation sequence IDs in the range \c fragment_list.seq_id \c -
+ * \c N_FRAG_BUF \c + \c 1 to \c fragment_list.seq_id, inclusive.
+ */
struct fragment fragments[N_FRAG_BUF];
};
-struct fragment_master {
- struct event_timeout wakeup; /* when should main openvpn event loop wake us up */
-
- /* true if the OS has explicitly recommended an MTU value */
- bool received_os_mtu_hint;
- /* a sequence ID describes a set of fragments that make up one datagram */
-# define N_SEQ_ID 256 /* sequence number wraps to 0 at this value (should be a power of 2) */
- int outgoing_seq_id; /* sent as FRAG_SEQ_ID below */
-
- /* outgoing packet is possibly sent as a series of fragments */
-
-# define MAX_FRAG_PKT_SIZE 65536 /* maximum packet size */
- int outgoing_frag_size; /* sent to peer via FRAG_SIZE when FRAG_YES_LAST set */
-
- int outgoing_frag_id; /* each fragment in a datagram is numbered 0 to MAX_FRAGS-1 */
-
- struct buffer outgoing; /* outgoing datagram, free if current_frag_id == 0 */
- struct buffer outgoing_return; /* buffer to return outgoing fragment */
+/**
+ * Fragmentation and reassembly state for one VPN tunnel instance.
+ *
+ * This structure contains all the state necessary for sending and
+ * receiving fragmented data channel packets associated with one VPN
+ * tunnel.
+ *
+ * The fragmented packet currently being sent to a remote OpenVPN peer is
+ * stored in \c fragment_master.outgoing. It is copied into that buffer
+ * by the \c fragment_outgoing() function and the remaining parts to be
+ * sent can be retrieved by successive calls to \c
+ * fragment_ready_to_send().
+ *
+ * The received packets currently being reassembled are stored in the \c
+ * fragment_master.incoming array of \c fragment structures. The \c
+ * fragment_incoming() function adds newly received parts into this array
+ * and returns the whole packets once reassembly is complete.
+ */
+struct fragment_master {
+ struct event_timeout wakeup; /**< Timeout structure used by the main
+ * event loop to know when to do
+ * fragmentation housekeeping. */
+ bool received_os_mtu_hint; /**< Whether the operating system has
+ * explicitly recommended an MTU value. */
+# define N_SEQ_ID 256
+ /**< One more than the maximum fragment
+ * sequence ID, above which the IDs wrap
+ * to zero. Should be a power of 2. */
+ int outgoing_seq_id; /**< Fragment sequence ID of the current
+ * fragmented packet waiting to be sent.
+ *
+ * All parts of a fragmented packet
+ * share the same sequence ID, so that
+ * the remote OpenVPN peer can determine
+ * which parts belong to which original
+ * packet. */
+# define MAX_FRAG_PKT_SIZE 65536
+ /**< (Not used) Maximum packet size before
+ * fragmenting. */
+ int outgoing_frag_size; /**< Size in bytes of each part to be
+ * sent, except for the last part which
+ * may be smaller.
+ *
+ * This value is computed by the \c
+ * optimal_fragment_size() function. Its
+ * value is sent to the remote peer in
+ * the fragmentation header of the last
+ * part (i.e. with %fragment type \c
+ * FRAG_YES_LAST) using the \c
+ * FRAG_SIZE_MASK and \c FRAG_SIZE_SHIFT
+ * bits. */
+ int outgoing_frag_id; /**< The fragment ID of the next part to
+ * be sent. Must have a value between 0
+ * and \c MAX_FRAGS-1. */
+ struct buffer outgoing; /**< Buffer containing the remaining parts
+ * of the fragmented packet being sent. */
+ struct buffer outgoing_return;
+ /**< Buffer used by \c
+ * fragment_ready_to_send() to return a
+ * part to send. */
- /* incoming fragments from remote */
struct fragment_list incoming;
+ /**< List of structures for reassembling
+ * incoming packets. */
};
-/*
- * Fragment header sent over the wire.
- */
+
+/**************************************************************************/
+/** @name Fragment header
+ * @todo Add description of %fragment header format.
+ *//** @{ *//*************************************/
typedef uint32_t fragment_header_type;
+ /**< Fragmentation information is stored in
+ * a 32-bit packet header. */
-/* convert a fragment_header_type from host to network order */
#define hton_fragment_header_type(x) htonl(x)
+ /**< Convert a fragment_header_type from
+ * host to network order. */
-/* convert a fragment_header_type from network to host order */
#define ntoh_fragment_header_type(x) ntohl(x)
+ /**< Convert a \c fragment_header_type
+ * from network to host order. */
-/* FRAG_TYPE 2 bits */
#define FRAG_TYPE_MASK 0x00000003
-#define FRAG_TYPE_SHIFT 0
+ /**< Bit mask for %fragment type info. */
+#define FRAG_TYPE_SHIFT 0 /**< Bit shift for %fragment type info. */
+
+#define FRAG_WHOLE 0 /**< Fragment type indicating packet is
+ * whole. */
+#define FRAG_YES_NOTLAST 1 /**< Fragment type indicating packet is
+ * part of a fragmented packet, but not
+ * the last part in the sequence. */
+#define FRAG_YES_LAST 2 /**< Fragment type indicating packet is
+ * the last part in the sequence of
+ * parts. */
+#define FRAG_TEST 3 /**< Fragment type not implemented yet.
+ * In the future might be used as a
+ * control packet for establishing MTU
+ * size. */
-#define FRAG_WHOLE 0 /* packet is whole, FRAG_N_PACKETS_RECEIVED echoed back to peer */
-#define FRAG_YES_NOTLAST 1 /* packet is a fragment, but is not the last fragment,
- FRAG_N_PACKETS_RECEIVED set as above */
-#define FRAG_YES_LAST 2 /* packet is the last fragment, FRAG_SIZE = size of non-last frags */
-#define FRAG_TEST 3 /* control packet for establishing MTU size (not implemented yet) */
-
-/* FRAG_SEQ_ID 8 bits */
#define FRAG_SEQ_ID_MASK 0x000000ff
-#define FRAG_SEQ_ID_SHIFT 2
+ /**< Bit mask for %fragment sequence ID. */
+#define FRAG_SEQ_ID_SHIFT 2 /**< Bit shift for %fragment sequence ID. */
-/* FRAG_ID 5 bits */
#define FRAG_ID_MASK 0x0000001f
+ /**< Bit mask for %fragment ID. */
#define FRAG_ID_SHIFT 10
+ /**< Bit shift for %fragment ID. */
/*
* FRAG_SIZE 14 bits
*
* IF FRAG_YES_LAST (FRAG_SIZE):
- * The max size of a fragment. If a fragment is not the last fragment in the packet,
- * then the fragment size is guaranteed to be equal to the max fragment size. Therefore,
+ * The max size of a %fragment. If a %fragment is not the last %fragment in the packet,
+ * then the %fragment size is guaranteed to be equal to the max %fragment size. Therefore,
* max_frag_size is only sent over the wire if FRAG_LAST is set. Otherwise it is assumed
- * to be the actual fragment size received.
+ * to be the actual %fragment size received.
*/
-
-/* FRAG_SIZE 14 bits */
#define FRAG_SIZE_MASK 0x00003fff
+ /**< Bit mask for %fragment size. */
#define FRAG_SIZE_SHIFT 15
-#define FRAG_SIZE_ROUND_SHIFT 2 /* fragment/datagram sizes represented as multiple of 4 */
-
+ /**< Bit shift for %fragment size. */
+#define FRAG_SIZE_ROUND_SHIFT 2 /**< Bit shift for %fragment size rounding. */
#define FRAG_SIZE_ROUND_MASK ((1 << FRAG_SIZE_ROUND_SHIFT) - 1)
+ /**< Bit mask for %fragment size rounding. */
/*
* FRAG_EXTRA 16 bits
*
* IF FRAG_WHOLE or FRAG_YES_NOTLAST, these 16 bits are available (not currently used)
*/
-
-/* FRAG_EXTRA 16 bits */
#define FRAG_EXTRA_MASK 0x0000ffff
+ /**< Bit mask for extra bits. */
#define FRAG_EXTRA_SHIFT 15
+ /**< Bit shift for extra bits. */
-/*
- * Public functions
- */
+/** @} name Fragment header *//********************************************/
+
+/**************************************************************************/
+/** @name Functions for initialization and cleanup *//** @{ *//************/
+
+/**
+ * Allocate and initialize a \c fragment_master structure.
+ *
+ * This function also modifies the \a frame packet geometry parameters to
+ * include space for the fragmentation header.
+ *
+ * @param frame - The packet geometry parameters for this VPN
+ * tunnel, modified by this function to include the
+ * fragmentation header.
+ *
+ * @return A pointer to the new \c fragment_master structure.
+ */
struct fragment_master *fragment_init (struct frame *frame);
+
+/**
+ * Allocate internal packet buffers for a \c fragment_master structure.
+ *
+ * @param f - The \c fragment_master structure for which to
+ * allocate the internal buffers.
+ * @param frame - The packet geometry parameters for this VPN
+ * tunnel, used to determine how much memory to
+ * allocate for each packet buffer.
+ */
void fragment_frame_init (struct fragment_master *f, const struct frame *frame);
+
+/**
+ * Free a \c fragment_master structure and its internal packet buffers.
+ *
+ * @param f - The \c fragment_master structure to free.
+ */
void fragment_free (struct fragment_master *f);
+/** @} name Functions for initialization and cleanup *//*******************/
+
+
+/**************************************************************************/
+/** @name Functions for processing packets received from a remote OpenVPN peer */
+/** @{ */
+
+/**
+ * Process an incoming packet, which may or may not be fragmented.
+ *
+ * This function inspects the fragmentation header of the incoming packet
+ * and processes the packet accordingly. Depending on the %fragment type
+ * bits (\c FRAG_TYPE_MASK and \c FRAG_TYPE_SHIFT) the packet is processed
+ * in the following ways:
+ * - \c FRAG_WHOLE: the packet is not fragmented, and this function does
+ * not modify its contents, except for removing the fragmentation
+ * header.
+ * - \c FRAG_YES_NOTLAST or \c FRAG_YES_LAST: the packet is part of a
+ * fragmented packet. This function copies the packet into an internal
+ * reassembly buffer. If the incoming part completes the packet being
+ * reassembled, the \a buf argument is modified to point to the fully
+ * reassembled packet. If, on the other hand, reassembly is not yet
+ * complete, then the the \a buf buffer is set to empty.
+ * - Any other value: error.
+ *
+ * If an error occurs during processing, an error message is logged and
+ * the length of \a buf is set to zero.
+ *
+ * @param f - The \c fragment_master structure for this VPN
+ * tunnel.
+ * @param buf - A pointer to the buffer structure containing the
+ * incoming packet. This pointer will have been
+ * modified on return either to point to a
+ * completely reassembled packet, or to have length
+ * set to zero if reassembly is not yet complete.
+ * @param frame - The packet geometry parameters for this VPN
+ * tunnel.
+ *
+ * @return Void.\n On return, the \a buf argument will point to a buffer.
+ * The buffer will have nonzero length if the incoming packet passed
+ * to this function was whole and unfragmented, or if it was the final
+ * part of a fragmented packet thereby completing reassembly. On the
+ * other hand, the buffer will have a length of zero if the incoming
+ * packet was part of a fragmented packet and reassembly is not yet
+ * complete. If an error occurs during processing, the buffer length
+ * is also set to zero.
+ */
void fragment_incoming (struct fragment_master *f, struct buffer *buf,
const struct frame* frame);
+/** @} name Functions for processing packets received from a VPN tunnel */
+
+
+/**************************************************************************/
+/** @name Functions for processing packets to be sent to a remote OpenVPN peer */
+/** @{ */
+
+/**
+ * Process an outgoing packet, which may or may not need to be fragmented.
+ *
+ * This function inspects the outgoing packet, determines whether it needs
+ * to be fragmented, and processes it accordingly.
+ *
+ * Depending on the size of the outgoing packet and the packet geometry
+ * parameters for the VPN tunnel, the packet will or will not be
+ * fragmented.
+ * @li Packet size is less than or equal to the maximum packet size for
+ * this VPN tunnel: fragmentation is not necessary. The \a buf
+ * argument points to a buffer containing the unmodified outgoing
+ * packet with a fragmentation header indicating the packet is whole
+ * (FRAG_WHOLE) prepended.
+ * @li Packet size is greater than the maximum packet size for this VPN
+ * tunnel: fragmentation is necessary. The original outgoing packet
+ * is copied into an internal buffer for fragmentation. The \a buf
+ * argument is modified to point to the first part of the fragmented
+ * packet. The remaining parts remain stored in the internal buffer,
+ * and can be retrieved using the \c fragment_ready_to_send()
+ * function.
+ *
+ * If an error occurs during processing, an error message is logged and
+ * the length of \a buf is set to zero.
+ *
+ * @param f - The \c fragment_master structure for this VPN
+ * tunnel.
+ * @param buf - A pointer to the buffer structure containing the
+ * outgoing packet. This pointer will be modified
+ * to point to a whole unfragmented packet or to the
+ * first part of a fragmented packet on return.
+ * @param frame - The packet geometry parameters for this VPN
+ * tunnel.
+ *
+ * @return Void.\n On return, the \a buf argument will point to a buffer.
+ * This buffer contains either the whole original outgoing packet if
+ * fragmentation was not necessary, or the first part of the
+ * fragmented outgoing packet if fragmentation was necessary. In both
+ * cases a fragmentation header will have been prepended to inform the
+ * remote peer how to handle the packet.
+ */
void fragment_outgoing (struct fragment_master *f, struct buffer *buf,
const struct frame* frame);
+/**
+ * Check whether outgoing fragments are ready to be send, and if so make
+ * one available.
+ *
+ * This function checks whether the internal buffer for fragmenting
+ * outgoing packets contains any unsent parts. If it does not, meaning
+ * there is nothing waiting to be sent, it returns false. Otherwise there
+ * are parts ready to be sent, and it returns true. In that case it also
+ * modifies the \a buf argument to point to a buffer containing the next
+ * part to be sent.
+ *
+ * @param f - The \a fragment_master structure for this VPN
+ * tunnel.
+ * @param buf - A pointer to a buffer structure which on return,
+ * if there are parts waiting to be sent, will point
+ * to the next part to be sent.
+ * @param frame - The packet geometry parameters for this VPN
+ * tunnel.
+ *
+ * @return
+ * @li True, if an outgoing packet has been fragmented and not all parts
+ * have been sent yet. In this case this function will modify the \a
+ * buf argument to point to a buffer containing the next part to be
+ * sent.
+ * @li False, if there are no outgoing fragmented parts waiting to be
+ * sent.
+ */
bool fragment_ready_to_send (struct fragment_master *f, struct buffer *buf,
const struct frame* frame);
-/*
- * Private functions.
+/**
+ * Check whether a \c fragment_master structure contains fragments ready
+ * to be sent.
+ *
+ * @param f - The \c fragment_master structure for this VPN
+ * tunnel.
+ *
+ * @return
+ * @li True, if there are one or more fragments ready to be sent.
+ * @li False, otherwise.
*/
+static inline bool
+fragment_outgoing_defined (struct fragment_master *f)
+{
+ return f->outgoing.len > 0;
+}
+
+/** @} name Functions for processing packets going out through a VPN tunnel */
+
+
void fragment_wakeup (struct fragment_master *f, struct frame *frame);
-/*
- * Inline functions
- */
+/**************************************************************************/
+/** @name Functions for regular housekeeping *//** @{ *//******************/
+
+/**
+ * Perform housekeeping of a \c fragment_master structure.
+ *
+ * Housekeeping includes scanning incoming packet reassembly buffers for
+ * packets which have not yet been reassembled completely but are already
+ * older than their time-to-live.
+ *
+ * @param f - The \c fragment_master structure for this VPN
+ * tunnel.
+ * @param frame - The packet geometry parameters for this VPN
+ * tunnel.
+ */
static inline void
fragment_housekeeping (struct fragment_master *f, struct frame *frame, struct timeval *tv)
{
@@ -178,11 +469,11 @@ fragment_housekeeping (struct fragment_master *f, struct frame *frame, struct ti
fragment_wakeup (f, frame);
}
-static inline bool
-fragment_outgoing_defined (struct fragment_master *f)
-{
- return f->outgoing.len > 0;
-}
+/** @} name Functions for regular housekeeping *//*************************/
+
+
+/** @} addtogroup fragmentation *//****************************************/
+
#endif
#endif