OpenVPN
reliable.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23/*
24 * These routines implement a reliability layer on top of UDP,
25 * so that SSL/TLS can be run over UDP.
26 */
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
32#include "syshead.h"
33
34#include "buffer.h"
35#include "error.h"
36#include "common.h"
37#include "reliable.h"
38
39#include "memdbg.h"
40
41/* calculates test - base while allowing for base or test wraparound. test is
42 * assumed to be higher than base */
43static inline packet_id_type
45{
46 return test - base;
47}
48
49/*
50 * verify that test - base < extent while allowing for base or test wraparound
51 */
52static inline bool
54 const unsigned int extent)
55{
56 return subtract_pid(test, base) < extent;
57}
58
59/*
60 * verify that test < base + extent while allowing for base or test wraparound
61 */
62static inline bool
64 const unsigned int extent)
65{
66 if (base + extent >= base)
67 {
68 if (test < base + extent)
69 {
70 return true;
71 }
72 }
73 else
74 {
75 if ((test + 0x80000000u) < (base + 0x80000000u) + extent)
76 {
77 return true;
78 }
79 }
80
81 return false;
82}
83
84/*
85 * verify that p1 < p2 while allowing for p1 or p2 wraparound
86 */
87static inline bool
89{
90 return !reliable_pid_in_range1(p1, p2, 0x80000000u);
91}
92
93/* check if a particular packet_id is present in ack */
94static inline bool
96{
97 for (int i = 0; i < ack->len; ++i)
98 {
99 if (ack->packet_id[i] == pid)
100 {
101 return true;
102 }
103 }
104 return false;
105}
106
107/* get a packet_id from buf */
108bool
110{
111 packet_id_type net_pid;
112
113 if (buf_read(buf, &net_pid, sizeof(net_pid)))
114 {
115 *pid = ntohpid(net_pid);
116 dmsg(D_REL_DEBUG, "ACK read ID " packet_id_format " (buf->len=%d)",
117 (packet_id_print_type)*pid, buf->len);
118 return true;
119 }
120
121 dmsg(D_REL_LOW, "ACK read ID FAILED (buf->len=%d)", buf->len);
122 return false;
123}
124
125/* acknowledge a packet_id by adding it to a struct reliable_ack */
126bool
128{
130 {
131 ack->packet_id[ack->len++] = pid;
132 dmsg(D_REL_DEBUG, "ACK acknowledge ID " packet_id_format " (ack->len=%d)",
133 (packet_id_print_type)pid, ack->len);
134 return true;
135 }
136
137 dmsg(D_REL_LOW, "ACK acknowledge ID " packet_id_format " FAILED (ack->len=%d)",
138 (packet_id_print_type)pid, ack->len);
139 return false;
140}
141
142
143bool
144reliable_ack_read(struct reliable_ack *ack, struct buffer *buf, const struct session_id *sid)
145{
146 struct session_id session_id_remote;
147
148 if (!reliable_ack_parse(buf, ack, &session_id_remote))
149 {
150 return false;
151 }
152
153 if (ack->len >= 1
154 && (!session_id_defined(&session_id_remote) || !session_id_equal(&session_id_remote, sid)))
155 {
156 struct gc_arena gc = gc_new();
157 dmsg(D_REL_LOW, "ACK read BAD SESSION-ID FROM REMOTE, local=%s, remote=%s",
158 session_id_print(sid, &gc), session_id_print(&session_id_remote, &gc));
159 gc_free(&gc);
160 return false;
161 }
162 return true;
163}
164
165bool
166reliable_ack_parse(struct buffer *buf, struct reliable_ack *ack,
167 struct session_id *session_id_remote)
168{
169 uint8_t count;
170 ack->len = 0;
171
172 if (!buf_read(buf, &count, sizeof(count)))
173 {
174 return false;
175 }
176 for (int i = 0; i < count; ++i)
177 {
178 packet_id_type net_pid;
179 if (!buf_read(buf, &net_pid, sizeof(net_pid)))
180 {
181 return false;
182 }
183 if (ack->len >= RELIABLE_ACK_SIZE)
184 {
185 return false;
186 }
187 packet_id_type pid = ntohpid(net_pid);
188 ack->packet_id[ack->len++] = pid;
189 }
190 if (count)
191 {
192 if (!session_id_read(session_id_remote, buf))
193 {
194 return false;
195 }
196 }
197 return true;
198}
199
203void
204copy_acks_to_mru(struct reliable_ack *ack, struct reliable_ack *ack_mru, int n)
205{
206 ASSERT(ack->len >= n);
207 /* This loop is backward to ensure the same order as in ack */
208 for (int i = n - 1; i >= 0; i--)
209 {
210 packet_id_type id = ack->packet_id[i];
211
212 /* Handle special case of ack_mru empty */
213 if (ack_mru->len == 0)
214 {
215 ack_mru->len = 1;
216 ack_mru->packet_id[0] = id;
217 }
218
219 bool idfound = false;
220
221 /* Move all existing entries one to the right */
222 packet_id_type move = id;
223
224 for (int j = 0; j < ack_mru->len; j++)
225 {
226 packet_id_type tmp = ack_mru->packet_id[j];
227 ack_mru->packet_id[j] = move;
228 move = tmp;
229
230 if (move == id)
231 {
232 idfound = true;
233 break;
234 }
235 }
236
237 if (!idfound && ack_mru->len < RELIABLE_ACK_SIZE)
238 {
239 ack_mru->packet_id[ack_mru->len] = move;
240 ack_mru->len++;
241 }
242 }
243}
244
245/* write a packet ID acknowledgement record to buf, */
246/* removing all acknowledged entries from ack */
247bool
248reliable_ack_write(struct reliable_ack *ack, struct reliable_ack *ack_mru, struct buffer *buf,
249 const struct session_id *sid, int max, bool prepend)
250{
251 int i, j, n;
252 struct buffer sub;
253
254 n = ack->len;
255 if (n > max)
256 {
257 n = max;
258 }
259
261
262 /* Number of acks we can resend that still fit into the packet */
264
265 sub = buf_sub(buf, (int)ACK_SIZE(total_acks), prepend);
266 if (!BDEF(&sub))
267 {
268 goto error;
269 }
271
272 /* Write the actual acks to the packets. Since we copied the acks that
273 * are going out now already to the front of ack_mru we can fetch all
274 * acks from ack_mru */
275 for (i = 0; i < total_acks; ++i)
276 {
277 packet_id_type pid = ack_mru->packet_id[i];
279 ASSERT(buf_write(&sub, &net_pid, sizeof(net_pid)));
280 dmsg(D_REL_DEBUG, "ACK write ID " packet_id_format " (ack->len=%d, n=%d)",
281 (packet_id_print_type)pid, ack->len, n);
282 }
283 if (total_acks)
284 {
287 }
288 if (n)
289 {
290 for (i = 0, j = n; j < ack->len;)
291 {
292 ack->packet_id[i++] = ack->packet_id[j++];
293 }
294 ack->len = i;
295 }
296
297 return true;
298
299error:
300 return false;
301}
302
303/* print a reliable ACK record coming off the wire */
304const char *
305reliable_ack_print(struct buffer *buf, bool verbose, struct gc_arena *gc)
306{
308 struct buffer out = alloc_buf_gc(256, gc);
309
310 buf_printf(&out, "[");
311 if (!buf_read(buf, &n_ack, sizeof(n_ack)))
312 {
313 goto done;
314 }
315 for (int i = 0; i < n_ack; ++i)
316 {
318 if (!buf_read(buf, &pid, sizeof(pid)))
319 {
320 goto done;
321 }
322 pid = ntohpid(pid);
324 }
325 if (n_ack)
326 {
327 struct session_id sid_ack;
328 if (!session_id_read(&sid_ack, buf))
329 {
330 goto done;
331 }
332 if (verbose)
333 {
334 buf_printf(&out, " sid=%s", session_id_print(&sid_ack, gc));
335 }
336 }
337
338done:
339 buf_printf(&out, " ]");
340 return BSTR(&out);
341}
342
343/*
344 * struct reliable member functions.
345 */
346
347void
348reliable_init(struct reliable *rel, int buf_size, int offset, int array_size, bool hold)
349{
350 CLEAR(*rel);
351 ASSERT(array_size > 0 && array_size <= RELIABLE_CAPACITY);
352 rel->hold = hold;
353 rel->size = array_size;
354 rel->offset = offset;
355 for (int i = 0; i < rel->size; ++i)
356 {
357 struct reliable_entry *e = &rel->array[i];
358 e->buf = alloc_buf(buf_size);
359 ASSERT(buf_init(&e->buf, offset));
360 }
361}
362
363void
365{
366 if (!rel)
367 {
368 return;
369 }
370 for (int i = 0; i < rel->size; ++i)
371 {
372 struct reliable_entry *e = &rel->array[i];
373 free_buf(&e->buf);
374 }
375 free(rel);
376}
377
378/* no active buffers? */
379bool
380reliable_empty(const struct reliable *rel)
381{
382 for (int i = 0; i < rel->size; ++i)
383 {
384 const struct reliable_entry *e = &rel->array[i];
385 if (e->active)
386 {
387 return false;
388 }
389 }
390 return true;
391}
392
393int
399
400/* del acknowledged items from send buf */
401void
402reliable_send_purge(struct reliable *rel, const struct reliable_ack *ack)
403{
404 unsigned int out_of_window = 0;
405 packet_id_type first_out_of_window = 0;
406
407 for (int i = 0; i < ack->len; ++i)
408 {
409 packet_id_type pid = ack->packet_id[i];
410
411
412 if (!validate_packet_id_window(rel, pid))
413 {
414 if (out_of_window == 0)
415 {
416 first_out_of_window = pid;
417 }
418 out_of_window++;
419 continue;
420 }
421
422 for (int j = 0; j < rel->size; ++j)
423 {
424 struct reliable_entry *e = &rel->array[j];
425 if (e->active && e->packet_id == pid)
426 {
428 "ACK received for pid " packet_id_format ", deleting from send buffer",
430#if 0
431 /* DEBUGGING -- how close were we timing out on ACK failure and resending? */
432 {
433 if (e->next_try)
434 {
435 const interval_t wake = e->next_try - now;
436 msg(M_INFO, "ACK " packet_id_format ", wake=%d", pid, wake);
437 }
438 }
439#endif
440 e->active = false;
441 }
442
443 if (e->active && reliable_pid_min(e->packet_id, pid))
444 {
445 /* We have received an ACK for a packet with a higher PID. Either
446 * we have received ACKs out of or order or the packet has been
447 * lost. We count the number of ACKs to determine if we should
448 * resend it early. The comparison needs to be wraparound aware,
449 * otherwise a peer can inflate n_acks with an ACK for a pid from
450 * the lower half of the id space and force a retransmit. */
451 e->n_acks++;
452 }
453 }
454 }
455
456 if (out_of_window > 0)
457 {
458 (void)first_out_of_window; /* dmsg might not generate code */
459 dmsg(D_REL_LOW, "ACK contained %u ids outside the send window, "
460 "first was " packet_id_format,
461 out_of_window, (packet_id_print_type)first_out_of_window);
462 }
463}
464
465#ifdef ENABLE_DEBUG
466/* print the current sequence of active packet IDs */
467static const char *
468reliable_print_ids(const struct reliable *rel, struct gc_arena *gc)
469{
470 struct buffer out = alloc_buf_gc(256, gc);
471
472 buf_printf(&out, "[" packet_id_format "]", (packet_id_print_type)rel->packet_id);
473 for (int i = 0; i < rel->size; ++i)
474 {
475 const struct reliable_entry *e = &rel->array[i];
476 if (e->active)
477 {
479 }
480 }
481 return BSTR(&out);
482}
483#endif /* ENABLE_DEBUG */
484
485/* true if at least one free buffer available */
486bool
487reliable_can_get(const struct reliable *rel)
488{
489 for (int i = 0; i < rel->size; ++i)
490 {
491 const struct reliable_entry *e = &rel->array[i];
492 if (!e->active)
493 {
494 return true;
495 }
496 }
497 struct gc_arena gc = gc_new();
498 dmsg(D_REL_LOW, "ACK no free receive buffer available: %s", reliable_print_ids(rel, &gc));
499 gc_free(&gc);
500 return false;
501}
502
503/* make sure that incoming packet ID isn't a replay */
504bool
506{
507 struct gc_arena gc = gc_new();
508 if (reliable_pid_min(id, rel->packet_id))
509 {
510 goto bad;
511 }
512 for (int i = 0; i < rel->size; ++i)
513 {
514 const struct reliable_entry *e = &rel->array[i];
515 if (e->active && e->packet_id == id)
516 {
517 goto bad;
518 }
519 }
520 gc_free(&gc);
521 return true;
522
523bad:
524 dmsg(D_REL_DEBUG, "ACK " packet_id_format " is a replay: %s", (packet_id_print_type)id,
525 reliable_print_ids(rel, &gc));
526 gc_free(&gc);
527 return false;
528}
529
530/* make sure that incoming packet ID won't deadlock the receive buffer */
531bool
533{
534 const int ret = reliable_pid_in_range2(id, rel->packet_id, rel->size);
535
536 if (!ret)
537 {
538 struct gc_arena gc = gc_new();
539 dmsg(D_REL_LOW, "ACK " packet_id_format " breaks sequentiality: %s",
540 (packet_id_print_type)id, reliable_print_ids(rel, &gc));
541 gc_free(&gc);
542 }
543
544 dmsg(D_REL_DEBUG, "ACK RWBS rel->size=%d rel->packet_id=%08x id=%08x ret=%d", rel->size,
545 rel->packet_id, id, ret);
546 return ret;
547}
548
549/* grab a free buffer */
550struct buffer *
552{
553 for (int i = 0; i < rel->size; ++i)
554 {
555 struct reliable_entry *e = &rel->array[i];
556 if (!e->active)
557 {
558 ASSERT(buf_init(&e->buf, rel->offset));
559 return &e->buf;
560 }
561 }
562 return NULL;
563}
564
565int
567{
568 packet_id_type min_id = 0;
569 bool min_id_defined = false;
570
571 /* find minimum active packet_id */
572 for (int i = 0; i < rel->size; ++i)
573 {
574 const struct reliable_entry *e = &rel->array[i];
575 if (e->active)
576 {
577 if (!min_id_defined || reliable_pid_min(e->packet_id, min_id))
578 {
579 min_id_defined = true;
580 min_id = e->packet_id;
581 }
582 }
583 }
584
585 int ret = rel->size;
586 if (min_id_defined)
587 {
588 ret -= subtract_pid(rel->packet_id, min_id);
589 }
590 return ret;
591}
592
593/* grab a free buffer, fail if buffer clogged by unacknowledged low packet IDs */
594struct buffer *
596{
598 bool min_id_defined = false;
599 struct buffer *ret = NULL;
600
601 /* find minimum active packet_id */
602 for (int i = 0; i < rel->size; ++i)
603 {
604 const struct reliable_entry *e = &rel->array[i];
605 if (e->active)
606 {
607 if (!min_id_defined || reliable_pid_min(e->packet_id, min_id))
608 {
609 min_id_defined = true;
610 min_id = e->packet_id;
611 }
612 }
613 }
614
615 if (!min_id_defined || reliable_pid_in_range1(rel->packet_id, min_id, rel->size))
616 {
617 ret = reliable_get_buf(rel);
618 }
619 else
620 {
621 struct gc_arena gc = gc_new();
622 dmsg(D_REL_LOW, "ACK output sequence broken: %s", reliable_print_ids(rel, &gc));
623 gc_free(&gc);
624 }
625 return ret;
626}
627
628/* get active buffer for next sequentially increasing key ID */
629struct reliable_entry *
631{
632 for (int i = 0; i < rel->size; ++i)
633 {
634 struct reliable_entry *e = &rel->array[i];
635 if (e->active && e->packet_id == rel->packet_id)
636 {
637 return e;
638 }
639 }
640 return NULL;
641}
642
643/* return true if reliable_send would return a non-NULL result */
644bool
645reliable_can_send(const struct reliable *rel)
646{
647 struct gc_arena gc = gc_new();
648 int n_active = 0, n_current = 0;
649 for (int i = 0; i < rel->size; ++i)
650 {
651 const struct reliable_entry *e = &rel->array[i];
652 if (e->active)
653 {
654 ++n_active;
655 if (now >= e->next_try || e->n_acks >= N_ACK_RETRANSMIT)
656 {
657 ++n_current;
658 }
659 }
660 }
661 (void)n_active; /* dmsg might not generate code */
662 dmsg(D_REL_DEBUG, "ACK reliable_can_send active=%d current=%d : %s", n_active, n_current,
663 reliable_print_ids(rel, &gc));
664
665 gc_free(&gc);
666 return n_current > 0 && !rel->hold;
667}
668
669/* return next buffer to send to remote */
670struct buffer *
671reliable_send(struct reliable *rel, int *opcode)
672{
673 struct reliable_entry *best = NULL;
674 const time_t local_now = now;
675
676 for (int i = 0; i < rel->size; ++i)
677 {
678 struct reliable_entry *e = &rel->array[i];
679
680 /* If N_ACK_RETRANSMIT later packets have received ACKs, we assume
681 * that the packet was lost and resend it even if the timeout has
682 * not expired yet. */
683 if (e->active && (e->n_acks >= N_ACK_RETRANSMIT || local_now >= e->next_try))
684 {
685 if (!best || reliable_pid_min(e->packet_id, best->packet_id))
686 {
687 best = e;
688 }
689 }
690 }
691
692 if (best)
693 {
694 /* The initial timeout is bounded by RELIABLE_MAX_INITIAL_TIMEOUT, so
695 * shifting it cannot overflow. */
696 static_assert(RELIABLE_MAX_INITIAL_TIMEOUT <= (INT_MAX >> RELIABLE_MAX_TIMEOUT_SHIFT),
697 "initial reliable timeout overflows when shifted");
698 const interval_t max_timeout = rel->initial_timeout << RELIABLE_MAX_TIMEOUT_SHIFT;
699
700 /* exponential backoff */
701 best->next_try = local_now + best->timeout;
702 if (best->timeout < max_timeout)
703 {
704 best->timeout *= 2;
705 }
706
707 best->n_acks = 0;
708 *opcode = best->opcode;
709 dmsg(D_REL_DEBUG, "ACK reliable_send ID " packet_id_format " (size=%d to=%d)",
711 (int)(best->next_try - local_now));
712 return &best->buf;
713 }
714 return NULL;
715}
716
717/* schedule all pending packets for immediate retransmit */
718void
720{
721 dmsg(D_REL_DEBUG, "ACK reliable_schedule_now");
722 rel->hold = false;
723 for (int i = 0; i < rel->size; ++i)
724 {
725 struct reliable_entry *e = &rel->array[i];
726 if (e->active)
727 {
728 e->next_try = now;
729 e->timeout = rel->initial_timeout;
730 }
731 }
732}
733
734/* in how many seconds should we wake up to check for timeout */
735/* if we return BIG_TIMEOUT, nothing to wait for */
738{
739 struct gc_arena gc = gc_new();
741 const time_t local_now = now;
742
743 for (int i = 0; i < rel->size; ++i)
744 {
745 const struct reliable_entry *e = &rel->array[i];
746 if (e->active)
747 {
748 if (e->next_try <= local_now)
749 {
750 ret = 0;
751 break;
752 }
753 else
754 {
755 ret = min_int(ret, (int)(e->next_try - local_now));
756 }
757 }
758 }
759
760 dmsg(D_REL_DEBUG, "ACK reliable_send_timeout %d %s", (int)ret, reliable_print_ids(rel, &gc));
761
762 gc_free(&gc);
763 return ret;
764}
765
766/*
767 * Enable an incoming buffer previously returned by a get function as active.
768 */
769
770void
772 int opcode)
773{
774 for (int i = 0; i < rel->size; ++i)
775 {
776 struct reliable_entry *e = &rel->array[i];
777 if (buf == &e->buf)
778 {
779 e->active = true;
780
781 /* packets may not arrive in sequential order */
782 e->packet_id = pid;
783
784 /* check for replay */
785 ASSERT(!reliable_pid_min(pid, rel->packet_id));
786
787 e->opcode = opcode;
788 e->next_try = 0;
789 e->timeout = 0;
790 e->n_acks = 0;
791 dmsg(D_REL_DEBUG, "ACK mark active incoming ID " packet_id_format,
793 return;
794 }
795 }
796 ASSERT(0); /* buf not found in rel */
797}
798
799/*
800 * Enable an outgoing buffer previously returned by a get function as active.
801 */
802
803void
805{
806 for (int i = 0; i < rel->size; ++i)
807 {
808 struct reliable_entry *e = &rel->array[i];
809 if (buf == &e->buf)
810 {
811 /* Write mode, increment packet_id (i.e. sequence number)
812 * linearly and prepend id to packet */
813 packet_id_type net_pid;
814 e->packet_id = rel->packet_id++;
815 net_pid = htonpid(e->packet_id);
816 ASSERT(buf_write_prepend(buf, &net_pid, sizeof(net_pid)));
817 e->active = true;
818 e->opcode = opcode;
819 e->next_try = 0;
820 e->timeout = rel->initial_timeout;
821 dmsg(D_REL_DEBUG, "ACK mark active outgoing ID " packet_id_format,
823 return;
824 }
825 }
826 ASSERT(0); /* buf not found in rel */
827}
828
829/* delete a buffer previously activated by reliable_mark_active() */
830void
832{
833 for (int i = 0; i < rel->size; ++i)
834 {
835 struct reliable_entry *e = &rel->array[i];
836 if (buf == &e->buf)
837 {
838 e->active = false;
839 rel->packet_id = e->packet_id + 1;
840 return;
841 }
842 }
843 ASSERT(0);
844}
845
846#if 0
847
848void
849reliable_ack_debug_print(const struct reliable_ack *ack, char *desc)
850{
851 printf("********* struct reliable_ack %s\n", desc);
852 for (int i = 0; i < ack->len; ++i)
853 {
854 printf(" %d: " packet_id_format "\n", i, (packet_id_print_type) ack->packet_id[i]);
855 }
856}
857
858void
859reliable_debug_print(const struct reliable *rel, char *desc)
860{
861 update_time();
862
863 printf("********* struct reliable %s\n", desc);
864 printf(" initial_timeout=%d\n", (int)rel->initial_timeout);
865 printf(" packet_id=" packet_id_format "\n", rel->packet_id);
866 printf(" now=%" PRIi64 "\n", (int64_t)now);
867 for (int i = 0; i < rel->size; ++i)
868 {
869 const struct reliable_entry *e = &rel->array[i];
870 if (e->active)
871 {
872 printf(" %d: packet_id=" packet_id_format " len=%d", i, e->packet_id, e->buf.len);
873 printf(" next_try=%" PRIi64, (int64_t)e->next_try);
874 printf("\n");
875 }
876 }
877}
878
879#endif /* if 0 */
void free_buf(struct buffer *buf)
Free the memory allocated for a buffer.
Definition buffer.c:169
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
Definition buffer.c:226
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Return a sub-buffer of another buffer.
Definition buffer.c:207
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Definition buffer.c:77
struct buffer alloc_buf(size_t size)
Allocate a buffer of the given size.
Definition buffer.c:60
Buffer management functions and garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
Definition buffer.h:151
static bool buf_write_prepend(struct buffer *dest, const void *src, int size)
Prepend data to a buffer.
Definition buffer.h:1222
static bool buf_read(struct buffer *src, void *dest, int size)
Read bytes from the front of a buffer into a caller-supplied destination.
Definition buffer.h:1410
#define BDEF(buf)
Return true iff the buffer is defined (has non-NULL data pointer).
Definition buffer.h:149
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Append data to a buffer.
Definition buffer.h:1198
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Append a uint8_t to a buffer.
Definition buffer.h:1242
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1912
#define buf_init(buf, offset)
Definition buffer.h:356
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1896
int interval_t
Definition common.h:37
#define BIG_TIMEOUT
Definition common.h:42
#define D_REL_DEBUG
Definition errlevel.h:160
#define D_REL_LOW
Definition errlevel.h:122
#define M_INFO
Definition errlevel.h:54
void reliable_free(struct reliable *rel)
Free allocated memory associated with a reliable structure and the pointer itself.
Definition reliable.c:364
bool reliable_ack_read(struct reliable_ack *ack, struct buffer *buf, const struct session_id *sid)
Read an acknowledgment record from a received packet.
Definition reliable.c:144
struct buffer * reliable_get_buf_output_sequenced(struct reliable *rel)
Get the buffer of free reliable entry and check whether the outgoing acknowledgment sequence is still...
Definition reliable.c:595
void reliable_schedule_now(struct reliable *rel)
Reschedule all entries of a reliable structure to be ready for (re)sending immediately.
Definition reliable.c:719
void reliable_ack_debug_print(const struct reliable_ack *ack, char *desc)
bool reliable_ack_read_packet_id(struct buffer *buf, packet_id_type *pid)
Read the packet ID of a received packet.
Definition reliable.c:109
void reliable_mark_active_incoming(struct reliable *rel, struct buffer *buf, packet_id_type pid, int opcode)
Mark the reliable entry associated with the given buffer as active incoming.
Definition reliable.c:771
void reliable_mark_active_outgoing(struct reliable *rel, struct buffer *buf, int opcode)
Mark the reliable entry associated with the given buffer as active outgoing.
Definition reliable.c:804
const char * reliable_ack_print(struct buffer *buf, bool verbose, struct gc_arena *gc)
Definition reliable.c:305
bool reliable_ack_acknowledge_packet_id(struct reliable_ack *ack, packet_id_type pid)
Record a packet ID for later acknowledgment.
Definition reliable.c:127
#define RELIABLE_MAX_INITIAL_TIMEOUT
Maximum initial timeout (–tls-timeout) we accept.
Definition reliable.h:65
bool reliable_ack_parse(struct buffer *buf, struct reliable_ack *ack, struct session_id *session_id_remote)
Parse an acknowledgment record from a received packet.
Definition reliable.c:166
#define RELIABLE_MAX_TIMEOUT_SHIFT
Maximum shift or doubling in exponential backoff we allow.
Definition reliable.h:59
bool reliable_ack_write(struct reliable_ack *ack, struct reliable_ack *ack_mru, struct buffer *buf, const struct session_id *sid, int max, bool prepend)
Write a packet ID acknowledgment record to a buffer.
Definition reliable.c:248
#define N_ACK_RETRANSMIT
We retry sending a packet early if this many later packets have been ACKed.
Definition reliable.h:54
int validate_packet_id_window(struct reliable *rel, packet_id_type pid)
check that pid is inside the window of possible outstanding packets of size RELIABLE_CAPACITY,...
Definition reliable.c:394
bool reliable_can_get(const struct reliable *rel)
Check whether a reliable structure has any free buffers available for use.
Definition reliable.c:487
void reliable_send_purge(struct reliable *rel, const struct reliable_ack *ack)
Remove acknowledged packets from a reliable structure.
Definition reliable.c:402
struct buffer * reliable_get_buf(struct reliable *rel)
Get the buffer of a free reliable entry in which to store a packet.
Definition reliable.c:551
struct buffer * reliable_send(struct reliable *rel, int *opcode)
Get the next packet to send to the remote peer.
Definition reliable.c:671
bool reliable_can_send(const struct reliable *rel)
Check whether a reliable structure has any active entries ready to be (re)sent.
Definition reliable.c:645
bool reliable_empty(const struct reliable *rel)
Check whether a reliable structure is empty.
Definition reliable.c:380
void reliable_debug_print(const struct reliable *rel, char *desc)
bool reliable_not_replay(const struct reliable *rel, packet_id_type id)
Check that a received packet's ID is not a replay.
Definition reliable.c:505
#define RELIABLE_ACK_SIZE
The maximum number of packet IDs waiting to be acknowledged which can be stored in one reliable_ack s...
Definition reliable.h:43
interval_t reliable_send_timeout(const struct reliable *rel)
Determined how many seconds until the earliest resend should be attempted.
Definition reliable.c:737
#define RELIABLE_CAPACITY
The maximum number of packets that the reliability layer for one VPN tunnel in one direction can stor...
Definition reliable.h:49
struct reliable_entry * reliable_get_entry_sequenced(struct reliable *rel)
Get the buffer of the next sequential and active entry.
Definition reliable.c:630
void reliable_init(struct reliable *rel, int buf_size, int offset, int array_size, bool hold)
Initialize a reliable structure.
Definition reliable.c:348
void copy_acks_to_mru(struct reliable_ack *ack, struct reliable_ack *ack_mru, int n)
Copies the first n acks from ack to ack_mru.
Definition reliable.c:204
void reliable_mark_deleted(struct reliable *rel, struct buffer *buf)
Remove an entry from a reliable structure.
Definition reliable.c:831
int reliable_get_num_output_sequenced_available(struct reliable *rel)
Counts the number of free buffers in output that can be potentially used for sending.
Definition reliable.c:566
bool reliable_wont_break_sequentiality(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.
Definition reliable.c:532
#define ACK_SIZE(n)
Definition reliable.h:81
static int min_int(int x, int y)
Definition integer.h:105
#define CLEAR(x)
Definition basic.h:32
#define dmsg(flags,...)
Definition error.h:172
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:219
time_t now
Definition otime.c:33
static void update_time(void)
Definition otime.h:84
#define packet_id_format
Definition packet_id.h:76
#define htonpid(x)
Definition packet_id.h:61
uint64_t packet_id_print_type
Definition packet_id.h:77
uint32_t packet_id_type
Definition packet_id.h:45
#define ntohpid(x)
Definition packet_id.h:64
static packet_id_type subtract_pid(const packet_id_type test, const packet_id_type base)
Definition reliable.c:44
static bool reliable_ack_packet_id_present(struct reliable_ack *ack, packet_id_type pid)
Definition reliable.c:95
static bool reliable_pid_in_range1(const packet_id_type test, const packet_id_type base, const unsigned int extent)
Definition reliable.c:53
static bool reliable_pid_min(const packet_id_type p1, const packet_id_type p2)
Definition reliable.c:88
static bool reliable_pid_in_range2(const packet_id_type test, const packet_id_type base, const unsigned int extent)
Definition reliable.c:63
Reliability Layer module header file.
const char * session_id_print(const struct session_id *sid, struct gc_arena *gc)
Definition session_id.c:54
static bool session_id_write(const struct session_id *sid, struct buffer *buf)
Definition session_id.h:71
static bool session_id_equal(const struct session_id *sid1, const struct session_id *sid2)
Definition session_id.h:47
static bool session_id_defined(const struct session_id *sid1)
Definition session_id.h:53
static bool session_id_read(struct session_id *sid, struct buffer *buf)
Definition session_id.h:59
Wrapper structure for dynamically allocated memory.
Definition buffer.h:71
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:76
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:127
The acknowledgment structure in which packet IDs are stored for later acknowledgment.
Definition reliable.h:75
packet_id_type packet_id[RELIABLE_ACK_SIZE]
Definition reliable.h:77
The structure in which the reliability layer stores a single incoming or outgoing packet.
Definition reliable.h:88
struct buffer buf
Definition reliable.h:97
int opcode
Definition reliable.h:96
time_t next_try
Definition reliable.h:91
size_t n_acks
Definition reliable.h:93
packet_id_type packet_id
Definition reliable.h:92
bool active
Definition reliable.h:89
interval_t timeout
Definition reliable.h:90
The reliability layer storage structure for one VPN tunnel's control channel in one direction.
Definition reliable.h:105
struct reliable_entry array[RELIABLE_CAPACITY]
Definition reliable.h:111
bool hold
Definition reliable.h:110
int size
Definition reliable.h:106
packet_id_type packet_id
Packet ID for the next packet to be sent out.
Definition reliable.h:108
interval_t initial_timeout
Definition reliable.h:107
int offset
Offset of the bufs in the reliable_entry array.
Definition reliable.h:109
struct gc_arena gc
Definition test_ssl.c:122