blob: 2daab6e42964f811e86f5fb5d79604d571536bb4 [file] [log] [blame]
/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
*
* Copyright (C) 2002-2021 OpenVPN Inc <sales@openvpn.net>
*
* 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.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/**
* @file
* Reliability Layer module header file.
*/
#ifndef RELIABLE_H
#define RELIABLE_H
#include "basic.h"
#include "buffer.h"
#include "packet_id.h"
#include "session_id.h"
#include "mtu.h"
/** @addtogroup reliable
* @{ */
#define EXPONENTIAL_BACKOFF
#define RELIABLE_ACK_SIZE 8 /**< The maximum number of packet IDs
* waiting to be acknowledged which can
* be stored in one \c reliable_ack
* structure. */
#define RELIABLE_CAPACITY 8 /**< The maximum number of packets that
* the reliability layer for one VPN
* tunnel in one direction can store. */
/**
* The acknowledgment structure in which packet IDs are stored for later
* acknowledgment.
*/
struct reliable_ack
{
int len;
packet_id_type packet_id[RELIABLE_ACK_SIZE];
};
/**
* The structure in which the reliability layer stores a single incoming
* or outgoing packet.
*/
struct reliable_entry
{
bool active;
interval_t timeout;
time_t next_try;
packet_id_type packet_id;
int opcode;
struct buffer buf;
};
/**
* The reliability layer storage structure for one VPN tunnel's control
* channel in one direction.
*/
struct reliable
{
int size;
interval_t initial_timeout;
packet_id_type packet_id;
int offset;
bool hold; /* don't xmit until reliable_schedule_now is called */
struct reliable_entry array[RELIABLE_CAPACITY];
};
/**************************************************************************/
/** @name Functions for processing incoming acknowledgments
* @{ */
/**
* Read an acknowledgment record from a received packet.
*
* This function reads the packet ID acknowledgment record from the packet
* contained in \a buf. If the record contains acknowledgments, these are
* stored in \a ack. This function also compares the packet's session ID
* with the expected session ID \a sid, which should be equal.
*
* @param ack The acknowledgment structure in which received
* acknowledgments are to be stored.
* @param buf The buffer containing the packet.
* @param sid The expected session ID to compare to the session ID in
* the packet.
*
* @return
* @li True, if processing was successful.
* @li False, if an error occurs during processing.
*/
bool reliable_ack_read(struct reliable_ack *ack,
struct buffer *buf, const struct session_id *sid);
/**
* Remove acknowledged packets from a reliable structure.
*
* @param rel The reliable structure storing sent packets.
* @param ack The acknowledgment structure containing received
* acknowledgments.
*/
void reliable_send_purge(struct reliable *rel, const struct reliable_ack *ack);
/** @} name Functions for processing incoming acknowledgments */
/**************************************************************************/
/** @name Functions for processing outgoing acknowledgments
* @{ */
/**
* Check whether an acknowledgment structure contains any
* packet IDs to be acknowledged.
*
* @param ack The acknowledgment structure to check.
*
* @return
* @li True, if the acknowledgment structure is empty.
* @li False, if there are packet IDs to be acknowledged.
*/
static inline bool
reliable_ack_empty(struct reliable_ack *ack)
{
return !ack->len;
}
/**
* Write a packet ID acknowledgment record to a buffer.
*
* @param ack The acknowledgment structure containing packet IDs to be
* acknowledged.
* @param buf The buffer into which the acknowledgment record will be
* written.
* @param sid The session ID of the VPN tunnel associated with the
* packet IDs to be acknowledged.
* @param max The maximum number of acknowledgments to be written in
* the record.
* @param prepend If true, prepend the acknowledgment record in the
* buffer; if false, write into the buffer's current position.
*
* @return
* @li True, if processing was successful.
* @li False, if an error occurs during processing.
*/
bool reliable_ack_write(struct reliable_ack *ack,
struct buffer *buf,
const struct session_id *sid, int max, bool prepend);
/** @} name Functions for processing outgoing acknowledgments */
/**************************************************************************/
/** @name Functions for initialization and cleanup
* @{ */
/**
* Initialize a reliable structure.
*
* @param rel The reliable structure to initialize.
* @param buf_size The size of the buffers in which packets will be
* stored.
* @param offset The size of reserved space at the beginning of the
* buffers to allow efficient header prepending.
* @param array_size The number of packets that this reliable
* structure can store simultaneously.
* @param hold description
*/
void reliable_init(struct reliable *rel, int buf_size, int offset, int array_size, bool hold);
/**
* Free allocated memory associated with a reliable structure.
*
* @param rel The reliable structured to clean up.
*/
void reliable_free(struct reliable *rel);
/* add to extra_frame the maximum number of bytes we will need for reliable_ack_write */
void reliable_ack_adjust_frame_parameters(struct frame *frame, int max);
/** @} name Functions for initialization and cleanup */
/**************************************************************************/
/** @name Functions for inserting incoming packets
* @{ */
/**
* Check whether a reliable structure has any free buffers
* available for use.
*
* @param rel The reliable structure to check.
*
* @return
* @li True, if at least one buffer is available for use.
* @li False, if all the buffers are active.
*/
bool reliable_can_get(const struct reliable *rel);
/**
* Check that a received packet's ID is not a replay.
*
* @param rel The reliable structure for handling this VPN tunnel's
* received packets.
* @param id The packet ID of the received packet.
*
* @return
* @li True, if the packet ID is not a replay.
* @li False, if the packet ID is a replay.
*/
bool reliable_not_replay(const struct reliable *rel, packet_id_type id);
/**
* Check that a received packet's ID can safely be stored in
* the reliable structure's processing window.
*
* This function checks the difference between the received packet's ID
* and the lowest non-acknowledged packet ID in the given reliable
* structure. If that difference is larger than the total number of
* packets which can be stored, then this packet cannot be stored safely,
* because the reliable structure could possibly fill up without leaving
* room for all intervening packets. In that case, this received packet
* could break the reliable structure's sequentiality, and must therefore
* be discarded.
*
* @param rel The reliable structure for handling this VPN tunnel's
* received packets.
* @param id The packet ID of the received packet.
*
* @return
* @li True, if the packet can safely be stored.
* @li False, if the packet does not fit safely in the reliable
* structure's processing window.
*/
bool reliable_wont_break_sequentiality(const struct reliable *rel, packet_id_type id);
/**
* Read the packet ID of a received packet.
*
* @param buf The buffer containing the received packet.
* @param pid A pointer where the packet's packet ID will be written.
*
* @return
* @li True, if processing was successful.
* @li False, if an error occurs during processing.
*/
bool reliable_ack_read_packet_id(struct buffer *buf, packet_id_type *pid);
/**
* Get the buffer of a free %reliable entry in which to store a
* packet.
*
* @param rel The reliable structure in which to search for a free
* entry.
*
* @return A pointer to a buffer of a free entry in the \a rel
* reliable structure. If there are no free entries available, this
* function returns NULL.
*/
struct buffer *reliable_get_buf(struct reliable *rel);
/**
* Mark the %reliable entry associated with the given buffer as active
* incoming.
*
* @param rel The reliable structure associated with this packet.
* @param buf The buffer into which the packet has been copied.
* @param pid The packet's packet ID.
* @param opcode The packet's opcode.
*/
void reliable_mark_active_incoming(struct reliable *rel, struct buffer *buf,
packet_id_type pid, int opcode);
/**
* Record a packet ID for later acknowledgment.
*
* @param ack The acknowledgment structure which stores this VPN
* tunnel's packet IDs for later acknowledgment.
* @param pid The packet ID of the received packet which should be
* acknowledged.
*
* @return
* @li True, if the packet ID was added to \a ack.
* @li False, if the packet ID was already present in \a ack or \a ack
* has no free space to store any more packet IDs.
*/
bool reliable_ack_acknowledge_packet_id(struct reliable_ack *ack, packet_id_type pid);
/** @} name Functions for inserting incoming packets */
/**************************************************************************/
/** @name Functions for extracting incoming packets
* @{ */
/**
* Get the buffer of the next sequential and active entry.
*
* @param rel The reliable structure from which to retrieve the
* buffer.
*
* @return A pointer to the buffer of the entry with the next
* sequential key ID. If no such entry is present, this function
* returns NULL.
*/
struct buffer *reliable_get_buf_sequenced(struct reliable *rel);
/**
* Remove an entry from a reliable structure.
*
* @param rel The reliable structure associated with the given buffer.
* @param buf The buffer of the reliable entry which is to be removed.
* @param inc_pid If true, the reliable structure's packet ID counter
* will be incremented.
*/
void reliable_mark_deleted(struct reliable *rel, struct buffer *buf, bool inc_pid);
/** @} name Functions for extracting incoming packets */
/**************************************************************************/
/** @name Functions for inserting outgoing packets
* @{ */
/**
* Get the buffer of free reliable entry and check whether the
* outgoing acknowledgment sequence is still okay.
*
* @param rel The reliable structure in which to search for a free
* entry.
*
* @return A pointer to a buffer of a free entry in the \a rel
* reliable structure. If there are no free entries available, this
* function returns NULL. If the outgoing acknowledgment sequence is
* broken, this function also returns NULL.
*/
struct buffer *reliable_get_buf_output_sequenced(struct reliable *rel);
/**
* Mark the reliable entry associated with the given buffer as
* active outgoing.
*
* @param rel The reliable structure for handling this VPN tunnel's
* outgoing packets.
* @param buf The buffer previously returned by \c
* reliable_get_buf_output_sequenced() into which the packet has been
* copied.
* @param opcode The packet's opcode.
*/
void reliable_mark_active_outgoing(struct reliable *rel, struct buffer *buf, int opcode);
/** @} name Functions for inserting outgoing packets */
/**************************************************************************/
/** @name Functions for extracting outgoing packets
* @{ */
/**
* Check whether a reliable structure has any active entries
* ready to be (re)sent.
*
* @param rel The reliable structure to check.
*
* @return
* @li True, if there are active entries ready to be (re)sent
* president.
* @li False, if there are no active entries, or the active entries
* are not yet ready for resending.
*/
bool reliable_can_send(const struct reliable *rel);
/**
* Get the next packet to send to the remote peer.
*
* This function looks for the active entry ready for (re)sending with the
* lowest packet ID, and returns the buffer associated with it. This
* function also resets the timeout after which that entry will become
* ready for resending again.
*
* @param rel The reliable structure to check.
* @param opcode A pointer to an integer in which this function will
* store the opcode of the next packet to be sent.
*
* @return A pointer to the buffer of the next entry to be sent, or
* NULL if there are no entries ready for (re)sending present in the
* reliable structure. If a valid pointer is returned, then \a opcode
* will point to the opcode of that packet.
*/
struct buffer *reliable_send(struct reliable *rel, int *opcode);
/** @} name Functions for extracting outgoing packets */
/**************************************************************************/
/** @name Miscellaneous functions
* @{ */
/**
* Check whether a reliable structure is empty.
*
* @param rel The reliable structure to check.
*
* @return
* @li True, if there are no active entries in the given reliable
* structure.
* @li False, if there is at least one active entry present.
*/
bool reliable_empty(const struct reliable *rel);
/**
* Determined how many seconds until the earliest resend should
* be attempted.
*
* @param rel The reliable structured to check.
*
* @return The interval in seconds until the earliest resend attempt
* of the outgoing packets stored in the \a rel reliable structure. If
* the next time for attempting resending of one or more packets has
* already passed, this function will return 0.
*/
interval_t reliable_send_timeout(const struct reliable *rel);
/**
* Reschedule all entries of a reliable structure to be ready
* for (re)sending immediately.
*
* @param rel The reliable structure of which the entries should be
* modified.
*/
void reliable_schedule_now(struct reliable *rel);
void reliable_debug_print(const struct reliable *rel, char *desc);
/* set sending timeout (after this time we send again until ACK) */
static inline void
reliable_set_timeout(struct reliable *rel, interval_t timeout)
{
rel->initial_timeout = timeout;
}
/* print a reliable ACK record coming off the wire */
const char *reliable_ack_print(struct buffer *buf, bool verbose, struct gc_arena *gc);
void reliable_ack_debug_print(const struct reliable_ack *ack, char *desc);
/** @} name Miscellaneous functions */
/** @} addtogroup reliable */
#endif /* RELIABLE_H */