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