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