1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
|
/*
* 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-2005 OpenVPN Solutions LLC <info@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 (see the file COPYING included with this
* distribution); if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FRAGMENT_H
#define FRAGMENT_H
#ifdef ENABLE_FRAGMENT
#include "common.h"
#include "buffer.h"
#include "interval.h"
#include "mtu.h"
#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 */
struct fragment {
bool defined;
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 */
unsigned int map;
time_t timestamp; /* timestamp for time-to-live purposes */
struct buffer buf; /* fragment assembly buffer for received datagrams */
};
struct fragment_list {
int seq_id;
int index;
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 */
/* incoming fragments from remote */
struct fragment_list incoming;
};
/*
* Fragment header sent over the wire.
*/
typedef uint32_t fragment_header_type;
/* convert a fragment_header_type from host to network order */
#define hton_fragment_header_type(x) htonl(x)
/* convert a fragment_header_type from network to host order */
#define ntoh_fragment_header_type(x) ntohl(x)
/* FRAG_TYPE 2 bits */
#define FRAG_TYPE_MASK 0x00000003
#define FRAG_TYPE_SHIFT 0
#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
/* FRAG_ID 5 bits */
#define FRAG_ID_MASK 0x0000001f
#define FRAG_ID_SHIFT 10
/*
* 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,
* 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.
*/
/* FRAG_SIZE 14 bits */
#define FRAG_SIZE_MASK 0x00003fff
#define FRAG_SIZE_SHIFT 15
#define FRAG_SIZE_ROUND_SHIFT 2 /* fragment/datagram sizes represented as multiple of 4 */
#define FRAG_SIZE_ROUND_MASK ((1 << FRAG_SIZE_ROUND_SHIFT) - 1)
/*
* 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
#define FRAG_EXTRA_SHIFT 15
/*
* Public functions
*/
struct fragment_master *fragment_init (struct frame *frame);
void fragment_frame_init (struct fragment_master *f, const struct frame *frame);
void fragment_free (struct fragment_master *f);
void fragment_incoming (struct fragment_master *f, struct buffer *buf,
const struct frame* frame);
void fragment_outgoing (struct fragment_master *f, struct buffer *buf,
const struct frame* frame);
bool fragment_ready_to_send (struct fragment_master *f, struct buffer *buf,
const struct frame* frame);
/*
* Private functions.
*/
void fragment_wakeup (struct fragment_master *f, struct frame *frame);
/*
* Inline functions
*/
static inline void
fragment_housekeeping (struct fragment_master *f, struct frame *frame, struct timeval *tv)
{
if (event_timeout_trigger (&f->wakeup, tv, ETT_DEFAULT))
fragment_wakeup (f, frame);
}
static inline bool
fragment_outgoing_defined (struct fragment_master *f)
{
return f->outgoing.len > 0;
}
#endif
#endif
|