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