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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
|
/*
* 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-2017 OpenVPN Technologies, 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.
*/
#ifdef ENABLE_CRYPTO
#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, 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 */
#endif /* ENABLE_CRYPTO */
|