36void (*trace_set_time_hook) (
TIME);
37static int tracing_stopped;
38static int traceoutfile;
41static int trace_type_count;
42static int trace_type_max;
44static FILE *traceinfile;
46static int trace_playback_flag;
49#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
61 new_trace_types = tp -> next;
64 tp -> name = (
char *)0;
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);
78 trace_type_count = trace_type_max = 0;
86 unsigned,
const char *,
int);
90 return trace_playback_flag;
95 if (traceoutfile && !tracing_stopped)
104 static int root_setup = 0;
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;
134 log_error (
"%s(%d): trace_begin called twice",
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,
146 if (traceoutfile < 0) {
147 log_error (
"%s(%d): trace_begin: %s: %m",
149 return ISC_R_UNEXPECTED;
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);
161 status = write (traceoutfile, &tfh,
sizeof tfh);
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));
169 return ISC_R_UNEXPECTED;
173 if (new_trace_types) {
174 next = new_trace_types;
176 for (tptr = next; tptr; tptr = next) {
178 if (tptr -> index != 0) {
179 result = (trace_type_record
181 strlen (tptr -> name),
file,
line));
192 const char *buf,
const char *
file,
int line)
216 log_error (
"%s(%d): trace_write_packet with null trace type",
221 log_error (
"%s(%d): trace_write_packet with no tracefile.",
228 for (i = 0; i < count; i++)
229 length += iov [i].len;
233 memset(&tmp, 0,
sizeof(tmp));
235 tmp.
when = htonl (time ((time_t *)0));
236 tmp.
length = htonl (length);
238 status = write (traceoutfile, &tmp,
sizeof tmp);
240 log_error (
"%s(%d): trace_write_packet write failed: %m",
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));
249 for (i = 0; i < count; i++) {
250 status = write (traceoutfile, iov [i].buf, iov [i].len);
252 log_error (
"%s(%d): %s write failed: %m",
254 return ISC_R_UNEXPECTED;
255 }
else if (status != iov [i].len) {
256 log_error (
"%s(%d): %s: short write (%d:%d)",
258 "trace_write_packet", status, length);
267 static char zero [] = { 0, 0, 0, 0, 0, 0, 0 };
268 unsigned padl = 8 - (length % 8);
270 status = write (traceoutfile, zero, padl);
272 log_error (
"%s(%d): trace_write_packet write failed: %m",
274 return ISC_R_UNEXPECTED;
275 }
else if (status != padl) {
276 log_error (
"%s(%d): trace_write_packet: short write (%d:%d)",
289 if (trace_type_max <= tptr -> index) {
290 delta = tptr -> index - trace_type_max + 10;
291 vec =
dmalloc (((trace_type_max + delta) *
295 memset (&vec [trace_type_max], 0,
297 trace_type_max += delta;
299 memcpy (vec, trace_types,
305 trace_types [tptr -> index] = tptr;
306 if (tptr -> index >= trace_type_count)
307 trace_type_count = tptr -> index + 1;
318 unsigned slen = strlen (name);
330 strcpy (ttmp -> name, name);
331 ttmp -> have_packet = have_packet;
332 ttmp -> stop_tracing = stop_tracing;
335 status = trace_type_record (ttmp, slen,
file,
line);
342 ttmp -> next = new_trace_types;
343 new_trace_types = ttmp;
349static isc_result_t trace_type_record (
trace_type_t *ttmp,
unsigned slen,
357 return ISC_R_NOMEMORY;
358 ttmp -> index = ++traceindex;
360 tim -> index = htonl (ttmp -> index);
361 memcpy (tim -> name, ttmp -> name, slen);
375 for (i = 0; i < trace_type_count; i++)
376 if (trace_types [i] -> stop_tracing)
377 (*(trace_types [i] -> stop_tracing))
394 prev = &new_trace_types;
395 for (tptr = new_trace_types; tptr; tptr = tptr -> next) {
396 len = strlen (tptr -> name);
398 !memcmp (tptr -> name, tmap -> name, len)) {
399 tptr -> index = ntohl (tmap -> index);
401 *prev = tptr -> next;
404 prev = &tptr -> next;
407 log_error (
"No registered trace type for type name %.*s",
416 trace_playback_flag = 1;
430 traceinfile = fopen (filename,
"re");
432 log_error(
"Can't open tracefile %s: %m", filename);
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);
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");
445 log_error(
"Short read on trace file header: %d %ld.",
446 status, (
long)(
sizeof tracefile_header));
449 tracefile_header.
magic = ntohl(tracefile_header.
magic);
451 tracefile_header.
hlen = ntohl(tracefile_header.
hlen);
452 tracefile_header.
phlen = ntohl(tracefile_header.
phlen);
455 log_error(
"%s: not a dhcp trace file.", filename);
459 log_error (
"tracefile version %ld > current %ld.",
460 (
long int)tracefile_header.
version,
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);
470 len = (
sizeof tracefile_header) - tracefile_header.
hlen;
472 log_error(
"tracefile header size too small - %ld < %ld",
473 (
long int)tracefile_header.
hlen,
474 (
long int)
sizeof tracefile_header);
478 status = fseek(traceinfile, (
long)len, SEEK_CUR);
487 log_error (
"can't allocate trace packet header.");
510 char **buf,
unsigned *buflen,
515 int status, curposok = 0;
520 status = fgetpos(traceinfile, &curpos);
522 log_error(
"Can't save tracefile position: %m");
527 status = fread(tpkt, 1, (
size_t)tracefile_header.
phlen,
529 if (status < tracefile_header.
phlen) {
530 if (ferror(traceinfile))
531 log_error(
"Error reading trace packet header: "
533 else if (status == 0)
536 log_error (
"Short read on trace packet header:"
539 (
long int)tracefile_header.
phlen);
545 tpkt->
length = ntohl(tpkt -> length);
546 tpkt->
when = ntohl(tpkt -> when);
553 log_error (
"Trace packet with unknown index %ld",
570 if ((ttp != NULL) && (*ttp == NULL) &&
572 (trace_set_time_hook != NULL)) {
579 status = fsetpos(traceinfile, &curpos);
581 log_error(
"fsetpos in tracefile failed: %m");
585 (*trace_set_time_hook) (tpkt->
when);
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);
598 log_error (
"fsetpos in tracefile failed: %m");
601 return ISC_R_UNEXPECTEDTOKEN;
604 paylen = tpkt -> length;
606 paylen += 8 - (tpkt -> length % 8);
609 if ((*buf == NULL) || (paylen > (*bufmax))) {
612 (*bufmax) = ((paylen + 1023) & ~1023U);
615 log_error (
"Can't allocate input buffer sized %d",
617 return ISC_R_NOMEMORY;
621 status = fread ((*buf), 1, paylen, traceinfile);
622 if (status < paylen) {
623 if (ferror (traceinfile))
624 log_error (
"Error reading trace payload: %m");
626 log_error (
"Short read on trace payload: %d %d.",
632 *buflen = tpkt -> length;
640 unsigned *buflen,
char **buf)
651 log_error (
"can't allocate trace packet header.");
652 return ISC_R_NOMEMORY;
667 const char *filename,
unsigned *len,
char **buf)
676 if (!buf || !len || *buf)
680 status = fgetpos (traceinfile, &curpos);
682 log_error (
"Can't save tracefile position: %m");
686 log_error (
"can't allocate trace packet header.");
687 return ISC_R_NOMEMORY;
702 if (strcmp (filename, *buf)) {
703 log_error (
"Read file %s when expecting %s", *buf, filename);
707 status = fsetpos (traceinfile, &curpos);
709 log_error (
"fsetpos in tracefile failed: %m");
712 return ISC_R_UNEXPECTEDTOKEN;
isc_result_t omapi_array_free(omapi_array_t **, const char *, int)
void * dmalloc(size_t, const char *, int)
void dfree(void *, const char *, int)
int log_error(const char *,...) __attribute__((__format__(__printf__
#define DHCP_R_INVALIDARG
#define DHCP_R_PROTOCOLERROR
void(* have_packet)(trace_type_t *, unsigned, char *)
isc_result_t trace_get_file(trace_type_t *, const char *, unsigned *, char **)
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
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 *)
isc_result_t trace_init(void(*set_time)(time_t), const char *, int)
#define TRACE_INDEX_MAPPING_SIZE
#define TRACEFILE_VERSION