OpenVPN
Data Structures | Macros | Functions
Data Channel Fragmentation module

The Data Channel Fragmentation module offers fragmentation of data channel packets. More...

Data Structures

struct  fragment
 Structure for reassembling one incoming fragmented packet. More...
 
struct  fragment_list
 List of fragment structures for reassembling multiple incoming packets concurrently. More...
 
struct  fragment_master
 Fragmentation and reassembly state for one VPN tunnel instance. More...
 

Macros

#define N_FRAG_BUF   25
 Number of packet buffers for reassembling incoming fragmented packets. More...
 
#define FRAG_TTL_SEC   10
 Time-to-live in seconds for a fragment. More...
 
#define FRAG_WAKEUP_INTERVAL   5
 Interval in seconds between calls to wakeup code. More...
 

Functions

void fragment_wakeup (struct fragment_master *f, struct frame *frame)
 

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. More...
 
#define hton_fragment_header_type(x)   htonl(x)
 Convert a fragment_header_type from host to network order. More...
 
#define ntoh_fragment_header_type(x)   ntohl(x)
 Convert a fragment_header_type from network to host order. More...
 
#define FRAG_TYPE_MASK   0x00000003
 Bit mask for fragment type info. More...
 
#define FRAG_TYPE_SHIFT   0
 Bit shift for fragment type info. More...
 
#define FRAG_WHOLE   0
 Fragment type indicating packet is whole. More...
 
#define FRAG_YES_NOTLAST   1
 Fragment type indicating packet is part of a fragmented packet, but not the last part in the sequence. More...
 
#define FRAG_YES_LAST   2
 Fragment type indicating packet is the last part in the sequence of parts. More...
 
#define FRAG_TEST   3
 Fragment type not implemented yet. More...
 
#define FRAG_SEQ_ID_MASK   0x000000ff
 Bit mask for fragment sequence ID. More...
 
#define FRAG_SEQ_ID_SHIFT   2
 Bit shift for fragment sequence ID. More...
 
#define FRAG_ID_MASK   0x0000001f
 Bit mask for fragment ID. More...
 
#define FRAG_ID_SHIFT   10
 Bit shift for fragment ID. More...
 
#define FRAG_SIZE_MASK   0x00003fff
 Bit mask for fragment size. More...
 
#define FRAG_SIZE_SHIFT   15
 Bit shift for fragment size. More...
 
#define FRAG_SIZE_ROUND_SHIFT   2
 Bit shift for fragment size rounding. More...
 
#define FRAG_SIZE_ROUND_MASK   ((1 << FRAG_SIZE_ROUND_SHIFT) - 1)
 Bit mask for fragment size rounding. More...
 
#define FRAG_EXTRA_MASK   0x0000ffff
 Bit mask for extra bits. More...
 
#define FRAG_EXTRA_SHIFT   15
 Bit shift for extra bits. More...
 

Functions for initialization and cleanup

struct fragment_masterfragment_init (struct frame *frame)
 Allocate and initialize a fragment_master structure. More...
 
void fragment_frame_init (struct fragment_master *f, const struct frame *frame)
 Allocate internal packet buffers for a fragment_master structure. More...
 
void fragment_free (struct fragment_master *f)
 Free a fragment_master structure and its internal packet buffers. More...
 

Functions for processing packets received from a remote OpenVPN peer

void fragment_incoming (struct fragment_master *f, struct buffer *buf, const struct frame *frame)
 Process an incoming packet, which may or may not be fragmented. More...
 

Functions for processing packets to be sent to a remote OpenVPN peer

void fragment_outgoing (struct fragment_master *f, struct buffer *buf, const struct frame *frame)
 Process an outgoing packet, which may or may not need to be fragmented. More...
 
bool fragment_ready_to_send (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. More...
 
static bool fragment_outgoing_defined (struct fragment_master *f)
 Check whether a fragment_master structure contains fragments ready to be sent. More...
 

Functions for regular housekeeping

static void fragment_housekeeping (struct fragment_master *f, struct frame *frame, struct timeval *tv)
 Perform housekeeping of a fragment_master structure. More...
 

Detailed Description

The Data Channel Fragmentation module offers fragmentation of data channel packets.

State structures
The Data Channel Fragmentation module stores its internal state in a fragment_master structure. One such structure is present for each VPN tunnel, and is stored in context.c2.fragment of the context associated with that VPN tunnel.
The fragment_master structure contains one fragment_list structure fragment_master.incoming. This is a list of fragment structures, each of which can store the parts of one fragmented packet while it is being reassembled. The fragment_master structure also contains one buffer called fragment_master.outgoing, in which a data channel large packet to be sent to a remote OpenVPN peer can be broken up into parts to be sent one by one.
Initialization and cleanup
Every time a new fragment_master is needed, it must be allocated and initialized by the fragment_init() function. Similarly, every time a fragment_master is no longer needed, it must be cleaned up using the fragment_free() function. These functions take care of the allocation and freeing of the fragment_master structure itself and all internal memory required for the use of that structure. Note that this behavior is different from that displayed by the Data Channel Compression module.
Because of the one-to-one relationship between fragment_master structures and VPN tunnels, the above-mentioned initialization and cleanup functions are called directly from the init_instance() and close_instance() functions, which control the initialization and cleanup of VPN tunnel instances and their associated context structures.
Packet processing functions
This module receives data channel packets from the Data Channel Control module and processes them according to the settings of the packet's VPN tunnel. The Data Channel Control module uses the following interface functions:
  • For packets which will be sent to a remote OpenVPN peer: fragment_outgoing()
    This function inspects data channel packets as they are being made ready to be sent as VPN tunnel packets to a remote OpenVPN peer. If a packet's size is larger than its destination VPN tunnel's maximum transmission unit (MTU), then this module breaks that packet up into smaller parts, each of which is smaller than or equal to the VPN tunnel's MTU. See fragment_outgoing() for details.
  • For packets which have been received from a remote OpenVPN peer: fragment_incoming()
    This function inspects data channel packets that have been received from a remote OpenVPN peer through a VPN tunnel. It reads the fragmentation header of the packet, and depending on its value performs the appropriate action. See fragment_incoming() for details.
Settings that control this module's activity
Whether the Data Channel Fragmentation module is active or not depends on the compile-time ENABLE_FRAGMENT preprocessor macro and the runtime flag options.fragment, which gets its value from the process's configuration sources, such as the configuration file and commandline options.

Macro Definition Documentation

◆ FRAG_EXTRA_MASK

#define FRAG_EXTRA_MASK   0x0000ffff

Bit mask for extra bits.

Definition at line 260 of file fragment.h.

◆ FRAG_EXTRA_SHIFT

#define FRAG_EXTRA_SHIFT   15

Bit shift for extra bits.

Definition at line 262 of file fragment.h.

◆ FRAG_ID_MASK

#define FRAG_ID_MASK   0x0000001f

Bit mask for fragment ID.

Definition at line 233 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_ID_SHIFT

#define FRAG_ID_SHIFT   10

Bit shift for fragment ID.

Definition at line 235 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_SEQ_ID_MASK

#define FRAG_SEQ_ID_MASK   0x000000ff

Bit mask for fragment sequence ID.

Definition at line 229 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_SEQ_ID_SHIFT

#define FRAG_SEQ_ID_SHIFT   2

Bit shift for fragment sequence ID.

Definition at line 231 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_SIZE_MASK

#define FRAG_SIZE_MASK   0x00003fff

Bit mask for fragment size.

Definition at line 247 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_SIZE_ROUND_MASK

#define FRAG_SIZE_ROUND_MASK   ((1 << FRAG_SIZE_ROUND_SHIFT) - 1)

Bit mask for fragment size rounding.

Definition at line 252 of file fragment.h.

Referenced by fragment_incoming(), and optimal_fragment_size().

◆ FRAG_SIZE_ROUND_SHIFT

#define FRAG_SIZE_ROUND_SHIFT   2

Bit shift for fragment size rounding.

Definition at line 251 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_SIZE_SHIFT

#define FRAG_SIZE_SHIFT   15

Bit shift for fragment size.

Definition at line 249 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_TEST

#define FRAG_TEST   3

Fragment type not implemented yet.

In the future might be used as a control packet for establishing MTU size.

Definition at line 221 of file fragment.h.

Referenced by fragment_incoming().

◆ FRAG_TTL_SEC

#define FRAG_TTL_SEC   10

Time-to-live in seconds for a fragment.

Definition at line 54 of file fragment.h.

Referenced by fragment_ttl_reap().

◆ FRAG_TYPE_MASK

#define FRAG_TYPE_MASK   0x00000003

Bit mask for fragment type info.

Definition at line 204 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_TYPE_SHIFT

#define FRAG_TYPE_SHIFT   0

Bit shift for fragment type info.

Definition at line 206 of file fragment.h.

Referenced by fragment_incoming(), and fragment_prepend_flags().

◆ FRAG_WAKEUP_INTERVAL

#define FRAG_WAKEUP_INTERVAL   5

Interval in seconds between calls to wakeup code.

Definition at line 57 of file fragment.h.

Referenced by fragment_init().

◆ FRAG_WHOLE

#define FRAG_WHOLE   0

Fragment type indicating packet is whole.

Definition at line 208 of file fragment.h.

Referenced by fragment_incoming(), fragment_outgoing(), and fragment_prepend_flags().

◆ FRAG_YES_LAST

#define FRAG_YES_LAST   2

Fragment type indicating packet is the last part in the sequence of parts.

Definition at line 216 of file fragment.h.

Referenced by fragment_incoming(), and fragment_ready_to_send().

◆ FRAG_YES_NOTLAST

#define FRAG_YES_NOTLAST   1

Fragment type indicating packet is part of a fragmented packet, but not the last part in the sequence.

Definition at line 211 of file fragment.h.

Referenced by fragment_incoming(), fragment_prepend_flags(), and fragment_ready_to_send().

◆ hton_fragment_header_type

#define hton_fragment_header_type (   x)    htonl(x)

Convert a fragment_header_type from host to network order.

Definition at line 194 of file fragment.h.

Referenced by fragment_prepend_flags().

◆ N_FRAG_BUF

#define N_FRAG_BUF   25

Number of packet buffers for reassembling incoming fragmented packets.

Definition at line 49 of file fragment.h.

Referenced by fragment_list_buf_free(), fragment_list_buf_init(), fragment_list_get_buf(), and fragment_ttl_reap().

◆ ntoh_fragment_header_type

#define ntoh_fragment_header_type (   x)    ntohl(x)

Convert a fragment_header_type from network to host order.

Definition at line 199 of file fragment.h.

Referenced by fragment_incoming().

Typedef Documentation

◆ fragment_header_type

Fragmentation information is stored in a 32-bit packet header.

Definition at line 190 of file fragment.h.

Function Documentation

◆ fragment_frame_init()

void fragment_frame_init ( struct fragment_master f,
const struct frame frame 
)

Allocate internal packet buffers for a fragment_master structure.

Parameters
f- The fragment_master structure for which to allocate the internal buffers.
frame- The packet geometry parameters for this VPN tunnel, used to determine how much memory to allocate for each packet buffer.

Definition at line 126 of file fragment.c.

References alloc_buf(), BUF_SIZE, fragment_list_buf_init(), fragment_master::incoming, fragment_master::outgoing, and fragment_master::outgoing_return.

Referenced by do_init_fragment().

◆ fragment_free()

void fragment_free ( struct fragment_master f)

Free a fragment_master structure and its internal packet buffers.

Parameters
f- The fragment_master structure to free.

Definition at line 117 of file fragment.c.

References fragment_list_buf_free(), free_buf(), fragment_master::incoming, fragment_master::outgoing, and fragment_master::outgoing_return.

Referenced by do_close_fragment().

◆ fragment_housekeeping()

static void fragment_housekeeping ( struct fragment_master f,
struct frame frame,
struct timeval *  tv 
)
inlinestatic

Perform housekeeping of a 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.

Parameters
f- The fragment_master structure for this VPN tunnel.
frame- The packet geometry parameters for this VPN tunnel.

Definition at line 475 of file fragment.h.

Referenced by check_fragment_dowork().

◆ fragment_incoming()

void fragment_incoming ( struct fragment_master f,
struct buffer buf,
const struct frame frame 
)

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 (FRAG_TYPE_MASK and FRAG_TYPE_SHIFT) the packet is processed in the following ways:

  • FRAG_WHOLE: the packet is not fragmented, and this function does not modify its contents, except for removing the fragmentation header.
  • FRAG_YES_NOTLAST or 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 buf argument is modified to point to the fully reassembled packet. If, on the other hand, reassembly is not yet complete, then the the 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 buf is set to zero.

Parameters
f- The fragment_master structure for this VPN tunnel.
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.
frame- The packet geometry parameters for this VPN tunnel.
Returns
Void.
On return, the 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.

Definition at line 140 of file fragment.c.

References ASSERT, fragment::buf, buf_copy_range(), buf_init, buf_read(), D_FRAG_DEBUG, D_FRAG_ERRORS, fragment::defined, dmsg, FRAG_ERR, FRAG_ID_MASK, FRAG_ID_SHIFT, FRAG_MAP_MASK, FRAG_SEQ_ID_MASK, FRAG_SEQ_ID_SHIFT, FRAG_SIZE_MASK, FRAG_SIZE_ROUND_MASK, FRAG_SIZE_ROUND_SHIFT, FRAG_SIZE_SHIFT, FRAG_TEST, FRAG_TYPE_MASK, FRAG_TYPE_SHIFT, FRAG_WHOLE, FRAG_YES_LAST, FRAG_YES_NOTLAST, fragment_header_format, fragment_list_get_buf(), FRAME_HEADROOM_ADJ, FRAME_HEADROOM_MARKER_FRAGMENT, fragment_master::incoming, buffer::len, fragment::map, fragment::max_frag_size, msg, now, ntoh_fragment_header_type, and fragment::timestamp.

Referenced by process_incoming_link_part2().

◆ fragment_init()

struct fragment_master* fragment_init ( struct frame frame)

Allocate and initialize a fragment_master structure.

This function also modifies the frame packet geometry parameters to include space for the fragmentation header.

Parameters
frame- The packet geometry parameters for this VPN tunnel, modified by this function to include the fragmentation header.
Returns
A pointer to the new fragment_master structure.

Definition at line 90 of file fragment.c.

References ALLOC_OBJ_CLEAR, event_timeout_init(), FRAG_WAKEUP_INTERVAL, frame_add_to_extra_frame(), get_random(), N_SEQ_ID, now, fragment_master::outgoing_seq_id, and fragment_master::wakeup.

Referenced by init_instance().

◆ fragment_outgoing()

void fragment_outgoing ( struct fragment_master f,
struct buffer buf,
const struct frame frame 
)

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.

  • Packet size is less than or equal to the maximum packet size for this VPN tunnel: fragmentation is not necessary. The buf argument points to a buffer containing the unmodified outgoing packet with a fragmentation header indicating the packet is whole (FRAG_WHOLE) prepended.
  • 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 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 fragment_ready_to_send() function.

If an error occurs during processing, an error message is logged and the length of buf is set to zero.

Parameters
f- The fragment_master structure for this VPN tunnel.
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.
frame- The packet geometry parameters for this VPN tunnel.
Returns
Void.
On return, the 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.

Definition at line 325 of file fragment.c.

References ASSERT, buf_copy(), buf_init, D_FRAG_ERRORS, FRAG_ERR, FRAG_WHOLE, fragment_prepend_flags(), fragment_ready_to_send(), FRAME_HEADROOM, buffer::len, MAX_FRAGS, modulo_add(), msg, N_SEQ_ID, optimal_fragment_size(), fragment_master::outgoing, fragment_master::outgoing_frag_id, fragment_master::outgoing_frag_size, fragment_master::outgoing_seq_id, and PAYLOAD_SIZE_DYNAMIC.

Referenced by encrypt_sign().

◆ fragment_outgoing_defined()

static bool fragment_outgoing_defined ( struct fragment_master f)
inlinestatic

Check whether a fragment_master structure contains fragments ready to be sent.

Parameters
f- The fragment_master structure for this VPN tunnel.
Returns
  • True, if there are one or more fragments ready to be sent.
  • False, otherwise.

Definition at line 448 of file fragment.h.

References ETT_DEFAULT, event_timeout_trigger(), fragment_wakeup(), and fragment_master::wakeup.

Referenced by check_fragment_dowork(), and fragment_ready_to_send().

◆ fragment_ready_to_send()

bool fragment_ready_to_send ( 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 buf argument to point to a buffer containing the next part to be sent.

Parameters
f- The fragment_master structure for this VPN tunnel.
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.
frame- The packet geometry parameters for this VPN tunnel.
Returns
  • True, if an outgoing packet has been fragmented and not all parts have been sent yet. In this case this function will modify the buf argument to point to a buffer containing the next part to be sent.
  • False, if there are no outgoing fragmented parts waiting to be sent.

Definition at line 380 of file fragment.c.

References ASSERT, buf_copy_n(), buf_init, FRAG_YES_LAST, FRAG_YES_NOTLAST, fragment_outgoing_defined(), fragment_prepend_flags(), FRAME_HEADROOM, buffer::len, fragment_master::outgoing, fragment_master::outgoing_frag_id, fragment_master::outgoing_frag_size, fragment_master::outgoing_return, and fragment_master::outgoing_seq_id.

Referenced by check_fragment_dowork(), and fragment_outgoing().

◆ fragment_wakeup()

void fragment_wakeup ( struct fragment_master f,
struct frame frame 
)

Definition at line 433 of file fragment.c.

References dummy(), and fragment_ttl_reap().

Referenced by fragment_outgoing_defined().