ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
trace.c
Go to the documentation of this file.
1/* trace.c
2
3 Subroutines that support tracing of OMAPI wire transactions and
4 provide a mechanism for programs using OMAPI to trace their own
5 transactions... */
6
7/*
8 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 2001-2003 by Internet Software Consortium
10 *
11 * This Source Code Form is subject to the terms of the Mozilla Public
12 * License, v. 2.0. If a copy of the MPL was not distributed with this
13 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Internet Systems Consortium, Inc.
24 * PO Box 360
25 * Newmarket, NH 03857 USA
26 * <info@isc.org>
27 * https://www.isc.org/
28 *
29 */
30
31#include "dhcpd.h"
32#include <omapip/omapip_p.h>
33#include <errno.h>
34
35#if defined (TRACING)
36void (*trace_set_time_hook) (TIME);
37static int tracing_stopped;
38static int traceoutfile;
39static int traceindex;
40static trace_type_t **trace_types;
41static int trace_type_count;
42static int trace_type_max;
43static trace_type_t *new_trace_types;
44static FILE *traceinfile;
45static tracefile_header_t tracefile_header;
46static int trace_playback_flag;
47trace_type_t trace_time_marker;
48
49#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
50extern omapi_array_t *trace_listeners;
51extern omapi_array_t *omapi_connections;
52
53extern int errno;
54
55void trace_free_all ()
56{
57 trace_type_t *tp;
58 int i;
59 tp = new_trace_types;
60 while (tp) {
61 new_trace_types = tp -> next;
62 if (tp -> name) {
63 dfree (tp -> name, MDL);
64 tp -> name = (char *)0;
65 }
66 dfree (tp, MDL);
67 tp = new_trace_types;
68 }
69 for (i = 0; i < trace_type_count; i++) {
70 if (trace_types [i]) {
71 if (trace_types [i] -> name)
72 dfree (trace_types [i] -> name, MDL);
73 dfree (trace_types [i], MDL);
74 }
75 }
76 dfree (trace_types, MDL);
77 trace_types = (trace_type_t **)0;
78 trace_type_count = trace_type_max = 0;
79
80 omapi_array_free (&trace_listeners, MDL);
81 omapi_array_free (&omapi_connections, MDL);
82}
83#endif
84
85static isc_result_t trace_type_record (trace_type_t *,
86 unsigned, const char *, int);
87
88int trace_playback ()
89{
90 return trace_playback_flag;
91}
92
93int trace_record ()
94{
95 if (traceoutfile && !tracing_stopped)
96 return 1;
97 return 0;
98}
99
100isc_result_t trace_init (void (*set_time) (TIME),
101 const char *file, int line)
102{
103 trace_type_t *root_type;
104 static int root_setup = 0;
105
106 if (root_setup)
107 return ISC_R_SUCCESS;
108
109 trace_set_time_hook = set_time;
110
111 root_type = trace_type_register ("trace-index-mapping",
112 (void *)0, trace_index_map_input,
114 if (!root_type)
115 return ISC_R_UNEXPECTED;
116 if (new_trace_types == root_type)
117 new_trace_types = new_trace_types -> next;
118 root_type -> index = 0;
119 trace_type_stash (root_type);
120
121 root_setup = 1;
122 return ISC_R_SUCCESS;
123}
124
125isc_result_t trace_begin (const char *filename,
126 const char *file, int line)
127{
129 int status;
130 trace_type_t *tptr, *next;
131 isc_result_t result;
132
133 if (traceoutfile) {
134 log_error ("%s(%d): trace_begin called twice",
135 file, line);
136 return DHCP_R_INVALIDARG;
137 }
138
139 traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL | O_CLOEXEC, 0600);
140 if (traceoutfile < 0 && errno == EEXIST) {
141 log_error ("WARNING: Overwriting trace file \"%s\"", filename);
142 traceoutfile = open (filename, O_WRONLY | O_EXCL | O_TRUNC | O_CLOEXEC,
143 0600);
144 }
145
146 if (traceoutfile < 0) {
147 log_error ("%s(%d): trace_begin: %s: %m",
148 file, line, filename);
149 return ISC_R_UNEXPECTED;
150 }
151#if defined (HAVE_SETFD)
152 if (fcntl (traceoutfile, F_SETFD, 1) < 0)
153 log_error ("Can't set close-on-exec on %s: %m", filename);
154#endif
155
156 tfh.magic = htonl (TRACEFILE_MAGIC);
157 tfh.version = htonl (TRACEFILE_VERSION);
158 tfh.hlen = htonl (sizeof (tracefile_header_t));
159 tfh.phlen = htonl (sizeof (tracepacket_t));
160
161 status = write (traceoutfile, &tfh, sizeof tfh);
162 if (status < 0) {
163 log_error ("%s(%d): trace_begin write failed: %m", file, line);
164 return ISC_R_UNEXPECTED;
165 } else if (status != sizeof tfh) {
166 log_error ("%s(%d): trace_begin: short write (%d:%ld)",
167 file, line, status, (long)(sizeof tfh));
168 trace_stop ();
169 return ISC_R_UNEXPECTED;
170 }
171
172 /* Stash all the types that have already been set up. */
173 if (new_trace_types) {
174 next = new_trace_types;
175 new_trace_types = (trace_type_t *)0;
176 for (tptr = next; tptr; tptr = next) {
177 next = tptr -> next;
178 if (tptr -> index != 0) {
179 result = (trace_type_record
180 (tptr,
181 strlen (tptr -> name), file, line));
182 if (result != ISC_R_SUCCESS)
183 return status;
184 }
185 }
186 }
187
188 return ISC_R_SUCCESS;
189}
190
191isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length,
192 const char *buf, const char *file, int line)
193{
194 trace_iov_t iov;
195
196 iov.buf = buf;
197 iov.len = length;
198 return trace_write_packet_iov (ttype, 1, &iov, file, line);
199}
200
201isc_result_t trace_write_packet_iov (trace_type_t *ttype,
202 int count, trace_iov_t *iov,
203 const char *file, int line)
204{
205 tracepacket_t tmp;
206 int status;
207 int i;
208 int length;
209
210 /* Really shouldn't get called here, but it may be hard to turn off
211 tracing midstream if the trace file write fails or something. */
212 if (tracing_stopped)
213 return 0;
214
215 if (!ttype) {
216 log_error ("%s(%d): trace_write_packet with null trace type",
217 file ? file : "<unknown file>", line);
218 return DHCP_R_INVALIDARG;
219 }
220 if (!traceoutfile) {
221 log_error ("%s(%d): trace_write_packet with no tracefile.",
222 file ? file : "<unknown file>", line);
223 return DHCP_R_INVALIDARG;
224 }
225
226 /* Compute the total length of the iov. */
227 length = 0;
228 for (i = 0; i < count; i++)
229 length += iov [i].len;
230
231 /* We have to swap out the data, because it may be read back on a
232 machine of different endianness. */
233 memset(&tmp, 0, sizeof(tmp));
234 tmp.type_index = htonl (ttype -> index);
235 tmp.when = htonl (time ((time_t *)0)); /* XXX */
236 tmp.length = htonl (length);
237
238 status = write (traceoutfile, &tmp, sizeof tmp);
239 if (status < 0) {
240 log_error ("%s(%d): trace_write_packet write failed: %m",
241 file, line);
242 return ISC_R_UNEXPECTED;
243 } else if (status != sizeof tmp) {
244 log_error ("%s(%d): trace_write_packet: short write (%d:%ld)",
245 file, line, status, (long)(sizeof tmp));
246 trace_stop ();
247 }
248
249 for (i = 0; i < count; i++) {
250 status = write (traceoutfile, iov [i].buf, iov [i].len);
251 if (status < 0) {
252 log_error ("%s(%d): %s write failed: %m",
253 file, line, "trace_write_packet");
254 return ISC_R_UNEXPECTED;
255 } else if (status != iov [i].len) {
256 log_error ("%s(%d): %s: short write (%d:%d)",
257 file, line,
258 "trace_write_packet", status, length);
259 trace_stop ();
260 }
261 }
262
263 /* Write padding on the end of the packet to align the next
264 packet to an 8-byte boundary. This is in case we decide to
265 use mmap in some clever way later on. */
266 if (length % 8) {
267 static char zero [] = { 0, 0, 0, 0, 0, 0, 0 };
268 unsigned padl = 8 - (length % 8);
269
270 status = write (traceoutfile, zero, padl);
271 if (status < 0) {
272 log_error ("%s(%d): trace_write_packet write failed: %m",
273 file, line);
274 return ISC_R_UNEXPECTED;
275 } else if (status != padl) {
276 log_error ("%s(%d): trace_write_packet: short write (%d:%d)",
277 file, line, status, padl);
278 trace_stop ();
279 }
280 }
281
282 return ISC_R_SUCCESS;
283}
284
286{
287 trace_type_t **vec;
288 int delta;
289 if (trace_type_max <= tptr -> index) {
290 delta = tptr -> index - trace_type_max + 10;
291 vec = dmalloc (((trace_type_max + delta) *
292 sizeof (trace_type_t *)), MDL);
293 if (!vec)
294 return;
295 memset (&vec [trace_type_max], 0,
296 (sizeof (trace_type_t *)) * delta);
297 trace_type_max += delta;
298 if (trace_types) {
299 memcpy (vec, trace_types,
300 trace_type_count * sizeof (trace_type_t *));
301 dfree (trace_types, MDL);
302 }
303 trace_types = vec;
304 }
305 trace_types [tptr -> index] = tptr;
306 if (tptr -> index >= trace_type_count)
307 trace_type_count = tptr -> index + 1;
308}
309
310trace_type_t *trace_type_register (const char *name,
311 void *baggage,
312 void (*have_packet) (trace_type_t *,
313 unsigned, char *),
314 void (*stop_tracing) (trace_type_t *),
315 const char *file, int line)
316{
317 trace_type_t *ttmp;
318 unsigned slen = strlen (name);
319 isc_result_t status;
320
321 ttmp = dmalloc (sizeof *ttmp, file, line);
322 if (!ttmp)
323 return ttmp;
324 ttmp -> index = -1;
325 ttmp -> name = dmalloc (slen + 1, file, line);
326 if (!ttmp -> name) {
327 dfree (ttmp, file, line);
328 return (trace_type_t *)0;
329 }
330 strcpy (ttmp -> name, name);
331 ttmp -> have_packet = have_packet;
332 ttmp -> stop_tracing = stop_tracing;
333
334 if (traceoutfile) {
335 status = trace_type_record (ttmp, slen, file, line);
336 if (status != ISC_R_SUCCESS) {
337 dfree (ttmp -> name, file, line);
338 dfree (ttmp, file, line);
339 return (trace_type_t *)0;
340 }
341 } else {
342 ttmp -> next = new_trace_types;
343 new_trace_types = ttmp;
344 }
345
346 return ttmp;
347}
348
349static isc_result_t trace_type_record (trace_type_t *ttmp, unsigned slen,
350 const char *file, int line)
351{
353 isc_result_t status;
354
355 tim = dmalloc (slen + TRACE_INDEX_MAPPING_SIZE, file, line);
356 if (!tim)
357 return ISC_R_NOMEMORY;
358 ttmp -> index = ++traceindex;
359 trace_type_stash (ttmp);
360 tim -> index = htonl (ttmp -> index);
361 memcpy (tim -> name, ttmp -> name, slen);
362 status = trace_write_packet (trace_types [0],
364 (char *)tim, file, line);
365 dfree (tim, file, line);
366 return status;
367}
368
369/* Stop all registered trace types from trying to trace. */
370
371void trace_stop (void)
372{
373 int i;
374
375 for (i = 0; i < trace_type_count; i++)
376 if (trace_types [i] -> stop_tracing)
377 (*(trace_types [i] -> stop_tracing))
378 (trace_types [i]);
379 tracing_stopped = 1;
380}
381
382void trace_index_map_input (trace_type_t *ttype, unsigned length, char *buf)
383{
385 unsigned len;
386 trace_type_t *tptr, **prev;
387
388 if (length < TRACE_INDEX_MAPPING_SIZE) {
389 log_error ("short trace index mapping");
390 return;
391 }
392 tmap = (trace_index_mapping_t *)buf;
393
394 prev = &new_trace_types;
395 for (tptr = new_trace_types; tptr; tptr = tptr -> next) {
396 len = strlen (tptr -> name);
397 if (len == length - TRACE_INDEX_MAPPING_SIZE &&
398 !memcmp (tptr -> name, tmap -> name, len)) {
399 tptr -> index = ntohl (tmap -> index);
400 trace_type_stash (tptr);
401 *prev = tptr -> next;
402 return;
403 }
404 prev = &tptr -> next;
405 }
406
407 log_error ("No registered trace type for type name %.*s",
408 (int)length - TRACE_INDEX_MAPPING_SIZE, tmap -> name);
409 return;
410}
411
413
414void trace_replay_init (void)
415{
416 trace_playback_flag = 1;
417}
418
419void trace_file_replay (const char *filename)
420{
421 tracepacket_t *tpkt = NULL;
422 int status;
423 char *buf = NULL;
424 unsigned buflen;
425 unsigned bufmax = 0;
426 trace_type_t *ttype = NULL;
427 isc_result_t result;
428 int len;
429
430 traceinfile = fopen (filename, "re");
431 if (!traceinfile) {
432 log_error("Can't open tracefile %s: %m", filename);
433 return;
434 }
435#if defined (HAVE_SETFD)
436 if (fcntl (fileno(traceinfile), F_SETFD, 1) < 0)
437 log_error("Can't set close-on-exec on %s: %m", filename);
438#endif
439 status = fread(&tracefile_header, 1,
440 sizeof tracefile_header, traceinfile);
441 if (status < sizeof tracefile_header) {
442 if (ferror(traceinfile))
443 log_error("Error reading trace file header: %m");
444 else
445 log_error("Short read on trace file header: %d %ld.",
446 status, (long)(sizeof tracefile_header));
447 goto out;
448 }
449 tracefile_header.magic = ntohl(tracefile_header.magic);
450 tracefile_header.version = ntohl(tracefile_header.version);
451 tracefile_header.hlen = ntohl(tracefile_header.hlen);
452 tracefile_header.phlen = ntohl(tracefile_header.phlen);
453
454 if (tracefile_header.magic != TRACEFILE_MAGIC) {
455 log_error("%s: not a dhcp trace file.", filename);
456 goto out;
457 }
458 if (tracefile_header.version > TRACEFILE_VERSION) {
459 log_error ("tracefile version %ld > current %ld.",
460 (long int)tracefile_header.version,
461 (long int)TRACEFILE_VERSION);
462 goto out;
463 }
464 if (tracefile_header.phlen < sizeof *tpkt) {
465 log_error("tracefile packet size too small - %ld < %ld",
466 (long int)tracefile_header.phlen,
467 (long int)sizeof *tpkt);
468 goto out;
469 }
470 len = (sizeof tracefile_header) - tracefile_header.hlen;
471 if (len < 0) {
472 log_error("tracefile header size too small - %ld < %ld",
473 (long int)tracefile_header.hlen,
474 (long int)sizeof tracefile_header);
475 goto out;
476 }
477 if (len > 0) {
478 status = fseek(traceinfile, (long)len, SEEK_CUR);
479 if (status < 0) {
480 log_error("can't seek past header: %m");
481 goto out;
482 }
483 }
484
485 tpkt = dmalloc((unsigned)tracefile_header.phlen, MDL);
486 if (tpkt == NULL) {
487 log_error ("can't allocate trace packet header.");
488 goto out;
489 }
490
491 while ((result = trace_get_next_packet(&ttype, tpkt, &buf, &buflen,
492 &bufmax)) == ISC_R_SUCCESS) {
493 (*ttype->have_packet)(ttype, tpkt->length, buf);
494 ttype = NULL;
495 }
496 out:
497 fclose(traceinfile);
498 if (buf != NULL)
499 dfree(buf, MDL);
500 if (tpkt != NULL)
501 dfree(tpkt, MDL);
502}
503
504/* Get the next packet from the file. If ttp points to a nonzero pointer
505 to a trace type structure, check the next packet to see if it's of the
506 expected type, and back off if not. */
507
508isc_result_t trace_get_next_packet (trace_type_t **ttp,
509 tracepacket_t *tpkt,
510 char **buf, unsigned *buflen,
511 unsigned *bufmax)
512{
513 trace_type_t *ttype;
514 unsigned paylen;
515 int status, curposok = 0;
516 fpos_t curpos;
517
518 while(1) {
519 curposok = 0;
520 status = fgetpos(traceinfile, &curpos);
521 if (status < 0) {
522 log_error("Can't save tracefile position: %m");
523 } else {
524 curposok = 1;
525 }
526
527 status = fread(tpkt, 1, (size_t)tracefile_header.phlen,
528 traceinfile);
529 if (status < tracefile_header.phlen) {
530 if (ferror(traceinfile))
531 log_error("Error reading trace packet header: "
532 "%m");
533 else if (status == 0)
534 return ISC_R_EOF;
535 else
536 log_error ("Short read on trace packet header:"
537 " %ld %ld.",
538 (long int)status,
539 (long int)tracefile_header.phlen);
541 }
542
543 /* Swap the packet. */
544 tpkt->type_index = ntohl(tpkt -> type_index);
545 tpkt->length = ntohl(tpkt -> length);
546 tpkt->when = ntohl(tpkt -> when);
547
548 /* See if there's a handler for this packet type. */
549 if (tpkt->type_index < trace_type_count &&
550 trace_types[tpkt->type_index])
551 ttype = trace_types[tpkt->type_index];
552 else {
553 log_error ("Trace packet with unknown index %ld",
554 (long int)tpkt->type_index);
556 }
557
558 /*
559 * Determine if we should try to expire any timer events.
560 * We do so if:
561 * we aren't looking for a specific type of packet
562 * we have a hook to use to update the timer
563 * the timestamp on the packet doesn't match the current time
564 * When we do so we rewind the file to the beginning of this
565 * packet and then try for a new packet. This allows
566 * any code triggered by a timeout to get the current packet
567 * while we get the next one.
568 */
569
570 if ((ttp != NULL) && (*ttp == NULL) &&
571 (tpkt->when != cur_tv.tv_sec) &&
572 (trace_set_time_hook != NULL)) {
573 if (curposok == 0) {
574 log_error("no curpos for fsetpos in "
575 "tracefile");
577 }
578
579 status = fsetpos(traceinfile, &curpos);
580 if (status < 0) {
581 log_error("fsetpos in tracefile failed: %m");
583 }
584
585 (*trace_set_time_hook) (tpkt->when);
586 continue;
587 }
588 break;
589 }
590
591 /* If we were supposed to get a particular kind of packet,
592 check to see that we got the right kind. */
593 if (ttp && *ttp && ttype != *ttp) {
594 log_error ("Read packet type %s when expecting %s",
595 ttype -> name, (*ttp) -> name);
596 status = fsetpos (traceinfile, &curpos);
597 if (status < 0) {
598 log_error ("fsetpos in tracefile failed: %m");
600 }
601 return ISC_R_UNEXPECTEDTOKEN;
602 }
603
604 paylen = tpkt -> length;
605 if (paylen % 8)
606 paylen += 8 - (tpkt -> length % 8);
607
608 /* allocate a buffer if we need one or current buffer is too small */
609 if ((*buf == NULL) || (paylen > (*bufmax))) {
610 if ((*buf))
611 dfree ((*buf), MDL);
612 (*bufmax) = ((paylen + 1023) & ~1023U);
613 (*buf) = dmalloc ((*bufmax), MDL);
614 if (!(*buf)) {
615 log_error ("Can't allocate input buffer sized %d",
616 (*bufmax));
617 return ISC_R_NOMEMORY;
618 }
619 }
620
621 status = fread ((*buf), 1, paylen, traceinfile);
622 if (status < paylen) {
623 if (ferror (traceinfile))
624 log_error ("Error reading trace payload: %m");
625 else
626 log_error ("Short read on trace payload: %d %d.",
627 status, paylen);
629 }
630
631 /* Store the actual length of the payload. */
632 *buflen = tpkt -> length;
633
634 if (ttp)
635 *ttp = ttype;
636 return ISC_R_SUCCESS;
637}
638
639isc_result_t trace_get_packet (trace_type_t **ttp,
640 unsigned *buflen, char **buf)
641{
642 tracepacket_t *tpkt;
643 unsigned bufmax = 0;
644 isc_result_t status;
645
646 if (!buf || *buf)
647 return DHCP_R_INVALIDARG;
648
649 tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
650 if (!tpkt) {
651 log_error ("can't allocate trace packet header.");
652 return ISC_R_NOMEMORY;
653 }
654
655 status = trace_get_next_packet (ttp, tpkt, buf, buflen, &bufmax);
656
657 dfree (tpkt, MDL);
658 return status;
659}
660
661/* Get a packet from the trace input file that contains a file with the
662 specified name. We don't hunt for the packet - it should be the next
663 packet in the tracefile. If it's not, or something else bad happens,
664 return an error code. */
665
666isc_result_t trace_get_file (trace_type_t *ttype,
667 const char *filename, unsigned *len, char **buf)
668{
669 fpos_t curpos;
670 unsigned max = 0;
671 tracepacket_t *tpkt;
672 int status;
673 isc_result_t result;
674
675 /* Disallow some obvious bogosities. */
676 if (!buf || !len || *buf)
677 return DHCP_R_INVALIDARG;
678
679 /* Save file position in case of filename mismatch. */
680 status = fgetpos (traceinfile, &curpos);
681 if (status < 0)
682 log_error ("Can't save tracefile position: %m");
683
684 tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
685 if (!tpkt) {
686 log_error ("can't allocate trace packet header.");
687 return ISC_R_NOMEMORY;
688 }
689
690 result = trace_get_next_packet (&ttype, tpkt, buf, len, &max);
691 /* done with tpkt, free it */
692 dfree (tpkt, MDL);
693 if (result != ISC_R_SUCCESS) {
694 if (*buf) {
695 dfree (*buf, MDL);
696 *buf = NULL;
697 }
698 return result;
699 }
700
701 /* Make sure the filename is right. */
702 if (strcmp (filename, *buf)) {
703 log_error ("Read file %s when expecting %s", *buf, filename);
704 dfree (*buf, MDL);
705 *buf = NULL;
706
707 status = fsetpos (traceinfile, &curpos);
708 if (status < 0) {
709 log_error ("fsetpos in tracefile failed: %m");
711 }
712 return ISC_R_UNEXPECTEDTOKEN;
713 }
714
715 return ISC_R_SUCCESS;
716}
717#endif /* TRACING */
void set_time(TIME t)
Definition dispatch.c:36
time_t TIME
Definition dhcpd.h:85
struct timeval cur_tv
Definition dispatch.c:35
const char int line
Definition dhcpd.h:3802
const char * file
Definition dhcpd.h:3802
#define ISC_R_SUCCESS
#define MDL
Definition omapip.h:567
isc_result_t omapi_array_free(omapi_array_t **, const char *, int)
Definition array.c:53
void * dmalloc(size_t, const char *, int)
Definition alloc.c:57
void dfree(void *, const char *, int)
Definition alloc.c:145
int log_error(const char *,...) __attribute__((__format__(__printf__
#define DHCP_R_INVALIDARG
Definition result.h:49
#define DHCP_R_PROTOCOLERROR
Definition result.h:48
unsigned len
Definition trace.h:76
const char * buf
Definition trace.h:75
void(* have_packet)(trace_type_t *, unsigned, char *)
Definition trace.h:70
u_int32_t magic
Definition trace.h:35
u_int32_t version
Definition trace.h:36
int32_t phlen
Definition trace.h:38
int32_t hlen
Definition trace.h:37
u_int32_t when
Definition trace.h:52
u_int32_t type_index
Definition trace.h:48
u_int32_t length
Definition trace.h:50
isc_result_t trace_get_file(trace_type_t *, const char *, unsigned *, char **)
int trace_record(void)
struct trace_iov trace_iov_t
trace_type_t * trace_type_register(const char *, void *, void(*)(trace_type_t *, unsigned, char *), void(*)(trace_type_t *), const char *, int)
void trace_index_map_input(trace_type_t *, unsigned, char *)
void trace_index_stop_tracing(trace_type_t *)
isc_result_t trace_get_packet(trace_type_t **, unsigned *, char **)
void trace_free_all(void)
isc_result_t trace_begin(const char *, const char *, int)
isc_result_t trace_write_packet(trace_type_t *, unsigned, const char *, const char *, int)
void trace_file_replay(const char *)
void trace_type_stash(trace_type_t *)
struct trace_type trace_type_t
Definition trace.h:63
void trace_replay_init(void)
isc_result_t trace_write_packet_iov(trace_type_t *, int, trace_iov_t *, const char *, int)
isc_result_t trace_get_next_packet(trace_type_t **, tracepacket_t *, char **, unsigned *, unsigned *)
void trace_stop(void)
isc_result_t trace_init(void(*set_time)(time_t), const char *, int)
#define TRACE_INDEX_MAPPING_SIZE
Definition trace.h:56
#define TRACEFILE_MAGIC
Definition trace.h:29
int trace_playback(void)
#define TRACEFILE_VERSION
Definition trace.h:30