OpenVPN
packet_id.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single TCP/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-2017 OpenVPN Technologies, 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 are designed to catch replay attacks,
26  * where a man-in-the-middle captures packets and then
27  * attempts to replay them back later.
28  *
29  * We use the "sliding-window" algorithm, similar
30  * to IPSec.
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #elif defined(_MSC_VER)
36 #include "config-msvc.h"
37 #endif
38 
39 #include "syshead.h"
40 
41 #ifdef ENABLE_CRYPTO
42 
43 #include "packet_id.h"
44 #include "misc.h"
45 #include "integer.h"
46 
47 #include "memdbg.h"
48 
49 /* #define PID_SIMULATE_BACKTRACK */
50 
51 /*
52  * Special time_t value that indicates that
53  * sequence number has expired.
54  */
55 #define SEQ_UNSEEN ((time_t)0)
56 #define SEQ_EXPIRED ((time_t)1)
57 
58 static void packet_id_debug_print(int msglevel,
59  const struct packet_id_rec *p,
60  const struct packet_id_net *pin,
61  const char *message,
62  int value);
63 
64 static inline void
65 packet_id_debug(int msglevel,
66  const struct packet_id_rec *p,
67  const struct packet_id_net *pin,
68  const char *message,
69  int value)
70 {
71 #ifdef ENABLE_DEBUG
72  if (unlikely(check_debug_level(msglevel)))
73  {
74  packet_id_debug_print(msglevel, p, pin, message, value);
75  }
76 #endif
77 }
78 
79 void
80 packet_id_init(struct packet_id *p, int seq_backtrack, int time_backtrack, const char *name, int unit)
81 {
82  dmsg(D_PID_DEBUG, "PID packet_id_init seq_backtrack=%d time_backtrack=%d",
83  seq_backtrack,
84  time_backtrack);
85 
86  ASSERT(p);
87  CLEAR(*p);
88 
89  p->rec.name = name;
90  p->rec.unit = unit;
91  if (seq_backtrack)
92  {
93  ASSERT(MIN_SEQ_BACKTRACK <= seq_backtrack && seq_backtrack <= MAX_SEQ_BACKTRACK);
94  ASSERT(MIN_TIME_BACKTRACK <= time_backtrack && time_backtrack <= MAX_TIME_BACKTRACK);
95  CIRC_LIST_ALLOC(p->rec.seq_list, struct seq_list, seq_backtrack);
96  p->rec.seq_backtrack = seq_backtrack;
97  p->rec.time_backtrack = time_backtrack;
98  }
99  p->rec.initialized = true;
100 }
101 
102 void
104 {
105  if (p)
106  {
107  dmsg(D_PID_DEBUG, "PID packet_id_free");
108  if (p->rec.seq_list)
109  {
110  free(p->rec.seq_list);
111  }
112  CLEAR(*p);
113  }
114 }
115 
116 void
117 packet_id_add(struct packet_id_rec *p, const struct packet_id_net *pin)
118 {
119  const time_t local_now = now;
120  if (p->seq_list)
121  {
122  packet_id_type diff;
123 
124  /*
125  * If time value increases, start a new
126  * sequence number sequence.
127  */
128  if (!CIRC_LIST_SIZE(p->seq_list)
129  || pin->time > p->time
130  || (pin->id >= (packet_id_type)p->seq_backtrack
131  && pin->id - (packet_id_type)p->seq_backtrack > p->id))
132  {
133  p->time = pin->time;
134  p->id = 0;
135  if (pin->id > (packet_id_type)p->seq_backtrack)
136  {
137  p->id = pin->id - (packet_id_type)p->seq_backtrack;
138  }
140  }
141 
142  while (p->id < pin->id
143 #ifdef PID_SIMULATE_BACKTRACK
144  || (get_random() % 64) < 31
145 #endif
146  )
147  {
149  ++p->id;
150  }
151 
152  diff = p->id - pin->id;
153  if (diff < (packet_id_type) CIRC_LIST_SIZE(p->seq_list)
154  && local_now > SEQ_EXPIRED)
155  {
156  CIRC_LIST_ITEM(p->seq_list, diff) = local_now;
157  }
158  }
159  else
160  {
161  p->time = pin->time;
162  p->id = pin->id;
163  }
164 }
165 
166 /*
167  * Expire sequence numbers which can no longer
168  * be accepted because they would violate
169  * time_backtrack.
170  */
171 void
173 {
174  const time_t local_now = now;
175  if (p->time_backtrack)
176  {
177  int i;
178  bool expire = false;
179  for (i = 0; i < CIRC_LIST_SIZE(p->seq_list); ++i)
180  {
181  const time_t t = CIRC_LIST_ITEM(p->seq_list, i);
182  if (t == SEQ_EXPIRED)
183  {
184  break;
185  }
186  if (!expire && t && t + p->time_backtrack < local_now)
187  {
188  expire = true;
189  }
190  if (expire)
191  {
193  }
194  }
195  }
196  p->last_reap = local_now;
197 }
198 
199 /*
200  * Return true if packet id is ok, or false if
201  * it is a replay.
202  */
203 bool
205  const struct packet_id_net *pin)
206 {
207  packet_id_type diff;
208 
209  packet_id_debug(D_PID_DEBUG, p, pin, "PID_TEST", 0);
210 
211  ASSERT(p->initialized);
212 
213  if (!pin->id)
214  {
215  return false;
216  }
217 
218  if (p->seq_backtrack)
219  {
220  /*
221  * In backtrack mode, we allow packet reordering subject
222  * to the seq_backtrack and time_backtrack constraints.
223  *
224  * This mode is used with UDP.
225  */
226  if (pin->time == p->time)
227  {
228  /* is packet-id greater than any one we've seen yet? */
229  if (pin->id > p->id)
230  {
231  return true;
232  }
233 
234  /* check packet-id sliding window for original/replay status */
235  diff = p->id - pin->id;
236 
237  /* keep track of maximum backtrack seen for debugging purposes */
238  if ((int)diff > p->max_backtrack_stat)
239  {
240  p->max_backtrack_stat = (int)diff;
241  packet_id_debug(D_PID_DEBUG_LOW, p, pin, "PID_ERR replay-window backtrack occurred", p->max_backtrack_stat);
242  }
243 
244  if (diff >= (packet_id_type) CIRC_LIST_SIZE(p->seq_list))
245  {
246  packet_id_debug(D_PID_DEBUG_LOW, p, pin, "PID_ERR large diff", diff);
247  return false;
248  }
249 
250  {
251  const time_t v = CIRC_LIST_ITEM(p->seq_list, diff);
252  if (v == 0)
253  {
254  return true;
255  }
256  else
257  {
258  /* raised from D_PID_DEBUG_LOW to reduce verbosity */
259  packet_id_debug(D_PID_DEBUG_MEDIUM, p, pin, "PID_ERR replay", diff);
260  return false;
261  }
262  }
263  }
264  else if (pin->time < p->time) /* if time goes back, reject */
265  {
266  packet_id_debug(D_PID_DEBUG_LOW, p, pin, "PID_ERR time backtrack", 0);
267  return false;
268  }
269  else /* time moved forward */
270  {
271  return true;
272  }
273  }
274  else
275  {
276  /*
277  * In non-backtrack mode, all sequence number series must
278  * begin at some number n > 0 and must increment linearly without gaps.
279  *
280  * This mode is used with TCP.
281  */
282  if (pin->time == p->time)
283  {
284  return !p->id || pin->id == p->id + 1;
285  }
286  else if (pin->time < p->time) /* if time goes back, reject */
287  {
288  return false;
289  }
290  else /* time moved forward */
291  {
292  return pin->id == 1;
293  }
294  }
295 }
296 
297 /*
298  * Read/write a packet ID to/from the buffer. Short form is sequence number
299  * only. Long form is sequence number and timestamp.
300  */
301 
302 bool
303 packet_id_read(struct packet_id_net *pin, struct buffer *buf, bool long_form)
304 {
305  packet_id_type net_id;
306  net_time_t net_time;
307 
308  pin->id = 0;
309  pin->time = 0;
310 
311  if (!buf_read(buf, &net_id, sizeof(net_id)))
312  {
313  return false;
314  }
315  pin->id = ntohpid(net_id);
316  if (long_form)
317  {
318  if (!buf_read(buf, &net_time, sizeof(net_time)))
319  {
320  return false;
321  }
322  pin->time = ntohtime(net_time);
323  }
324  return true;
325 }
326 
327 static bool
328 packet_id_send_update(struct packet_id_send *p, bool long_form)
329 {
330  if (!p->time)
331  {
332  p->time = now;
333  }
334  if (p->id == PACKET_ID_MAX)
335  {
336  /* Packet ID only allowed to roll over if using long form and time has
337  * moved forward since last roll over.
338  */
339  if (!long_form || now <= p->time)
340  {
341  return false;
342  }
343  p->time = now;
344  p->id = 0;
345  }
346  p->id++;
347  return true;
348 }
349 
350 bool
351 packet_id_write(struct packet_id_send *p, struct buffer *buf, bool long_form,
352  bool prepend)
353 {
354  if (!packet_id_send_update(p, long_form))
355  {
356  return false;
357  }
358 
359  const packet_id_type net_id = htonpid(p->id);
360  const net_time_t net_time = htontime(p->time);
361  if (prepend)
362  {
363  if (long_form)
364  {
365  if (!buf_write_prepend(buf, &net_time, sizeof(net_time)))
366  {
367  return false;
368  }
369  }
370  if (!buf_write_prepend(buf, &net_id, sizeof(net_id)))
371  {
372  return false;
373  }
374  }
375  else
376  {
377  if (!buf_write(buf, &net_id, sizeof(net_id)))
378  {
379  return false;
380  }
381  if (long_form)
382  {
383  if (!buf_write(buf, &net_time, sizeof(net_time)))
384  {
385  return false;
386  }
387  }
388  }
389  return true;
390 }
391 
392 const char *
393 packet_id_net_print(const struct packet_id_net *pin, bool print_timestamp, struct gc_arena *gc)
394 {
395  struct buffer out = alloc_buf_gc(256, gc);
396 
398  if (print_timestamp && pin->time)
399  {
400  buf_printf(&out, " / time = (" packet_id_format ") %s",
402  time_string(pin->time, 0, false, gc));
403  }
404 
405  buf_printf(&out, " ]");
406  return BSTR(&out);
407 }
408 
409 /* initialize the packet_id_persist structure in a disabled state */
410 void
412 {
413  p->filename = NULL;
414  p->fd = -1;
415  p->time = p->time_last_written = 0;
416  p->id = p->id_last_written = 0;
417 }
418 
419 /* close the file descriptor if it is open, and switch to disabled state */
420 void
422 {
424  {
425  if (close(p->fd))
426  {
427  msg(D_PID_PERSIST | M_ERRNO, "Close error on --replay-persist file %s", p->filename);
428  }
430  }
431 }
432 
433 /* load persisted rec packet_id (time and id) only once from file, and set state to enabled */
434 void
435 packet_id_persist_load(struct packet_id_persist *p, const char *filename)
436 {
437  struct gc_arena gc = gc_new();
439  {
440  /* open packet-id persist file for both read and write */
441  p->fd = platform_open(filename,
442  O_CREAT | O_RDWR | O_BINARY,
443  S_IRUSR | S_IWUSR);
444  if (p->fd == -1)
445  {
447  "Cannot open --replay-persist file %s for read/write",
448  filename);
449  }
450  else
451  {
452  struct packet_id_persist_file_image image;
453  ssize_t n;
454 
455 #if defined(HAVE_FLOCK) && defined(LOCK_EX) && defined(LOCK_NB)
456  if (flock(p->fd, LOCK_EX | LOCK_NB))
457  {
458  msg(M_ERR, "Cannot obtain exclusive lock on --replay-persist file %s", filename);
459  }
460 #endif
461 
462  p->filename = filename;
463  n = read(p->fd, &image, sizeof(image));
464  if (n == sizeof(image))
465  {
466  p->time = p->time_last_written = image.time;
467  p->id = p->id_last_written = image.id;
468  dmsg(D_PID_PERSIST_DEBUG, "PID Persist Read from %s: %s",
469  p->filename, packet_id_persist_print(p, &gc));
470  }
471  else if (n == -1)
472  {
474  "Read error on --replay-persist file %s",
475  p->filename);
476  }
477  }
478  }
479  gc_free(&gc);
480 }
481 
482 /* save persisted rec packet_id (time and id) to file (only if enabled state) */
483 void
485 {
486  if (packet_id_persist_enabled(p) && p->time && (p->time != p->time_last_written
487  || p->id != p->id_last_written))
488  {
489  struct packet_id_persist_file_image image;
490  ssize_t n;
491  off_t seek_ret;
492  struct gc_arena gc = gc_new();
493 
494  image.time = p->time;
495  image.id = p->id;
496  seek_ret = lseek(p->fd, (off_t)0, SEEK_SET);
497  if (seek_ret == (off_t)0)
498  {
499  n = write(p->fd, &image, sizeof(image));
500  if (n == sizeof(image))
501  {
502  p->time_last_written = p->time;
503  p->id_last_written = p->id;
504  dmsg(D_PID_PERSIST_DEBUG, "PID Persist Write to %s: %s",
505  p->filename, packet_id_persist_print(p, &gc));
506  }
507  else
508  {
510  "Cannot write to --replay-persist file %s",
511  p->filename);
512  }
513  }
514  else
515  {
517  "Cannot seek to beginning of --replay-persist file %s",
518  p->filename);
519  }
520  gc_free(&gc);
521  }
522 }
523 
524 /* transfer packet_id_persist -> packet_id */
525 void
527 {
528  if (p && pid && packet_id_persist_enabled(p) && p->time)
529  {
530  pid->rec.time = p->time;
531  pid->rec.id = p->id;
532  }
533 }
534 
535 const char *
537 {
538  struct buffer out = alloc_buf_gc(256, gc);
539 
540  buf_printf(&out, "[");
541 
543  {
545  if (p->time)
546  {
547  buf_printf(&out, " / time = (" packet_id_format ") %s",
549  time_string(p->time, 0, false, gc));
550  }
551  }
552 
553  buf_printf(&out, " ]");
554  return (char *)out.data;
555 }
556 
557 #ifdef ENABLE_DEBUG
558 
559 static void
560 packet_id_debug_print(int msglevel,
561  const struct packet_id_rec *p,
562  const struct packet_id_net *pin,
563  const char *message,
564  int value)
565 {
566  struct gc_arena gc = gc_new();
567  struct buffer out = alloc_buf_gc(256, &gc);
568  struct timeval tv;
569  const time_t prev_now = now;
570  const struct seq_list *sl = p->seq_list;
571  int i;
572 
573  CLEAR(tv);
574  gettimeofday(&tv, NULL);
575 
576  buf_printf(&out, "%s [%d]", message, value);
577  buf_printf(&out, " [%s-%d] [", p->name, p->unit);
578  for (i = 0; sl != NULL && i < sl->x_size; ++i)
579  {
580  char c;
581  time_t v;
582  int diff;
583 
584  v = CIRC_LIST_ITEM(sl, i);
585  if (v == SEQ_UNSEEN)
586  {
587  c = '_';
588  }
589  else if (v == SEQ_EXPIRED)
590  {
591  c = 'E';
592  }
593  else
594  {
595  diff = (int) prev_now - v;
596  if (diff < 0)
597  {
598  c = 'N';
599  }
600  else if (diff < 10)
601  {
602  c = '0' + diff;
603  }
604  else
605  {
606  c = '>';
607  }
608  }
609  buf_printf(&out, "%c", c);
610  }
611  buf_printf(&out, "] %lld:" packet_id_format, (long long)p->time, (packet_id_print_type)p->id);
612  if (pin)
613  {
614  buf_printf(&out, " %lld:" packet_id_format, (long long)pin->time, (packet_id_print_type)pin->id);
615  }
616 
617  buf_printf(&out, " t=%lld[%d]",
618  (long long)prev_now,
619  (int)(prev_now - tv.tv_sec));
620 
621  buf_printf(&out, " r=[%d,%d,%d,%d,%d]",
622  (int)(p->last_reap - tv.tv_sec),
623  p->seq_backtrack,
624  p->time_backtrack,
626  (int)p->initialized);
627  if (sl != NULL)
628  {
629  buf_printf(&out, " sl=[%d,%d,%d,%d]",
630  sl->x_head,
631  sl->x_size,
632  sl->x_cap,
633  sl->x_sizeof);
634  }
635 
636 
637  msg(msglevel, "%s", BSTR(&out));
638  gc_free(&gc);
639 }
640 
641 #endif /* ifdef ENABLE_DEBUG */
642 
643 #ifdef PID_TEST
644 
645 void
646 packet_id_interactive_test(void)
647 {
648  struct packet_id pid;
649  struct packet_id_net pin;
650  bool long_form;
651  bool count = 0;
652  bool test;
653 
654  const int seq_backtrack = 10;
655  const int time_backtrack = 10;
656 
657  packet_id_init(&pid, seq_backtrack, time_backtrack);
658 
659  while (true)
660  {
661  char buf[80];
662  if (!fgets(buf, sizeof(buf), stdin))
663  {
664  break;
665  }
666  update_time();
667  if (sscanf(buf, "%lu,%u", &pin.time, &pin.id) == 2)
668  {
669  packet_id_reap_test(&pid.rec);
670  test = packet_id_test(&pid.rec, &pin);
671  printf("packet_id_test (%lld, " packet_id_format ") returned %d\n",
672  (long long)pin.time,
674  test);
675  if (test)
676  {
677  packet_id_add(&pid.rec, &pin);
678  }
679  }
680  else
681  {
682  long_form = (count < 20);
683  packet_id_alloc_outgoing(&pid.send, &pin, long_form);
684  printf("(%lld(" packet_id_format "), %d)\n",
685  (long long)pin.time,
687  long_form);
688  if (pid.send.id == 10)
689  {
690  pid.send.id = 0xFFFFFFF8;
691  }
692  ++count;
693  }
694  }
695  packet_id_free(&pid);
696 }
697 #endif /* ifdef PID_TEST */
698 
699 #endif /* ENABLE_CRYPTO */
int time_backtrack
Definition: packet_id.h:140
int max_backtrack_stat
Definition: packet_id.h:141
int seq_backtrack
Definition: packet_id.h:139
#define PACKET_ID_MAX
Definition: packet_id.h:52
#define D_PID_DEBUG_LOW
Definition: errlevel.h:107
void packet_id_persist_init(struct packet_id_persist *p)
Definition: packet_id.c:411
void packet_id_persist_load_obj(const struct packet_id_persist *p, struct packet_id *pid)
Definition: packet_id.c:526
static void gc_free(struct gc_arena *a)
Definition: buffer.h:990
static bool check_debug_level(unsigned int level)
Definition: error.h:245
#define ASSERT(x)
Definition: error.h:221
#define unlikely(x)
Definition: syshead.h:36
packet_id_type id
Definition: packet_id.h:203
#define htontime(x)
Definition: packet_id.h:69
#define CIRC_LIST_PUSH(obj, item)
Definition: circ_list.h:40
void packet_id_persist_close(struct packet_id_persist *p)
Definition: packet_id.c:421
#define packet_id_format
Definition: packet_id.h:97
#define D_PID_DEBUG_MEDIUM
Definition: errlevel.h:108
bool buf_printf(struct buffer *buf, const char *format,...)
Definition: buffer.c:223
packet_id_type id_last_written
Definition: packet_id.h:159
time_t last_reap
Definition: packet_id.h:136
time_t time_last_written
Definition: packet_id.h:158
#define CLEAR(x)
Definition: basic.h:33
const char * name
Definition: packet_id.h:144
time_t time
Definition: packet_id.h:137
bool packet_id_read(struct packet_id_net *pin, struct buffer *buf, bool long_form)
Definition: packet_id.c:303
const char * packet_id_persist_print(const struct packet_id_persist *p, struct gc_arena *gc)
Definition: packet_id.c:536
#define MIN_TIME_BACKTRACK
Definition: packet_id.h:114
struct packet_id_rec rec
Definition: packet_id.h:210
#define S_IWUSR
Definition: config-msvc.h:108
void packet_id_free(struct packet_id *p)
Definition: packet_id.c:103
static bool buf_read(struct buffer *src, void *dest, int size)
Definition: buffer.h:774
void packet_id_add(struct packet_id_rec *p, const struct packet_id_net *pin)
Definition: packet_id.c:117
static bool buf_write(struct buffer *dest, const void *src, int size)
Definition: buffer.h:663
bool packet_id_write(struct packet_id_send *p, struct buffer *buf, bool long_form, bool prepend)
Write a packet ID to buf, and update the packet ID state.
Definition: packet_id.c:351
const char * packet_id_net_print(const struct packet_id_net *pin, bool print_timestamp, struct gc_arena *gc)
Definition: packet_id.c:393
void packet_id_init(struct packet_id *p, int seq_backtrack, int time_backtrack, const char *name, int unit)
Definition: packet_id.c:80
static void packet_id_debug(int msglevel, const struct packet_id_rec *p, const struct packet_id_net *pin, const char *message, int value)
Definition: packet_id.c:65
uint32_t net_time_t
Definition: packet_id.h:53
packet_id_type id
Definition: packet_id.h:138
unsigned int packet_id_print_type
Definition: packet_id.h:98
int platform_open(const char *path, int flags, int mode)
Definition: platform.c:313
static void packet_id_reap_test(struct packet_id_rec *p)
Definition: packet_id.h:336
#define CIRC_LIST_ALLOC(dest, list_type, size)
Definition: circ_list.h:64
static struct gc_arena gc_new(void)
Definition: buffer.h:982
struct seq_list * seq_list
Definition: packet_id.h:143
time_t now
Definition: otime.c:36
bool packet_id_test(struct packet_id_rec *p, const struct packet_id_net *pin)
Definition: packet_id.c:204
time_t time
Definition: packet_id.h:204
#define ntohpid(x)
Definition: packet_id.h:66
#define M_ERR
Definition: error.h:110
const char * time_string(time_t t, int usec, bool show_usec, struct gc_arena *gc)
Definition: otime.c:114
#define D_PID_PERSIST_DEBUG
Definition: errlevel.h:165
const char * filename
Definition: packet_id.h:154
#define S_IRUSR
Definition: config-msvc.h:107
static void packet_id_debug_print(int msglevel, const struct packet_id_rec *p, const struct packet_id_net *pin, const char *message, int value)
#define SEQ_EXPIRED
Definition: packet_id.c:56
#define ntohtime(x)
Definition: packet_id.h:72
packet_id_type id
Definition: packet_id.h:157
struct packet_id_send send
Definition: packet_id.h:209
uint8_t * data
Pointer to the allocated memory.
Definition: buffer.h:68
#define MIN_SEQ_BACKTRACK
Definition: packet_id.h:105
#define dmsg
Definition: error.h:174
#define CIRC_LIST_ITEM(obj, index)
Definition: circ_list.h:55
#define O_BINARY
Definition: syshead.h:470
#define MAX_SEQ_BACKTRACK
Definition: packet_id.h:106
bool initialized
Definition: packet_id.h:142
#define msg
Definition: error.h:173
#define SEQ_UNSEEN
Definition: packet_id.c:55
#define htonpid(x)
Definition: packet_id.h:63
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
static bool buf_write_prepend(struct buffer *dest, const void *src, int size)
Definition: buffer.h:675
void packet_id_persist_load(struct packet_id_persist *p, const char *filename)
Definition: packet_id.c:435
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:88
uint32_t packet_id_type
Definition: packet_id.h:51
#define CIRC_LIST_RESET(obj)
Definition: circ_list.h:58
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
static bool packet_id_persist_enabled(const struct packet_id_persist *p)
Definition: packet_id.h:283
static bool packet_id_send_update(struct packet_id_send *p, bool long_form)
Definition: packet_id.c:328
#define BSTR(buf)
Definition: buffer.h:129
long int get_random(void)
Definition: crypto.c:1788
#define CIRC_LIST_SIZE(obj)
Definition: circ_list.h:47
#define D_PID_DEBUG
Definition: errlevel.h:146
#define M_ERRNO
Definition: error.h:99
void packet_id_persist_save(struct packet_id_persist *p)
Definition: packet_id.c:484
static void update_time(void)
Definition: otime.h:93
void packet_id_reap(struct packet_id_rec *p)
Definition: packet_id.c:172
#define ssize_t
Definition: config-msvc.h:105
#define D_PID_PERSIST
Definition: errlevel.h:68
packet_id_type id
Definition: packet_id.h:174
#define MAX_TIME_BACKTRACK
Definition: packet_id.h:115