38 void (*trace_set_time_hook) (
TIME);
39 static int tracing_stopped;
40 static int traceoutfile;
41 static int traceindex;
43 static int trace_type_count;
44 static int trace_type_max;
46 static FILE *traceinfile;
48 static int trace_playback_flag;
51 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) 63 new_trace_types = tp -> next;
66 tp -> name = (
char *)0;
71 for (i = 0; i < trace_type_count; i++) {
72 if (trace_types [i]) {
73 if (trace_types [i] -> name)
74 dfree (trace_types [i] -> name,
MDL);
80 trace_type_count = trace_type_max = 0;
88 unsigned,
const char *,
int);
92 return trace_playback_flag;
97 if (traceoutfile && !tracing_stopped)
106 static int root_setup = 0;
109 return ISC_R_SUCCESS;
117 return ISC_R_UNEXPECTED;
118 if (new_trace_types == root_type)
119 new_trace_types = new_trace_types -> next;
120 root_type -> index = 0;
124 return ISC_R_SUCCESS;
128 const char *file,
int line)
136 log_error (
"%s(%d): trace_begin called twice",
141 traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL | O_CLOEXEC, 0600);
142 if (traceoutfile < 0 && errno == EEXIST) {
143 log_error (
"WARNING: Overwriting trace file \"%s\"", filename);
144 traceoutfile = open (filename, O_WRONLY | O_EXCL | O_TRUNC | O_CLOEXEC,
148 if (traceoutfile < 0) {
149 log_error (
"%s(%d): trace_begin: %s: %m",
150 file, line, filename);
151 return ISC_R_UNEXPECTED;
153 #if defined (HAVE_SETFD) 154 if (fcntl (traceoutfile, F_SETFD, 1) < 0)
155 log_error (
"Can't set close-on-exec on %s: %m", filename);
163 status = write (traceoutfile, &tfh,
sizeof tfh);
165 log_error (
"%s(%d): trace_begin write failed: %m", file, line);
166 return ISC_R_UNEXPECTED;
167 }
else if (status !=
sizeof tfh) {
168 log_error (
"%s(%d): trace_begin: short write (%d:%ld)",
169 file, line, status, (
long)(
sizeof tfh));
171 return ISC_R_UNEXPECTED;
175 if (new_trace_types) {
176 next = new_trace_types;
178 for (tptr = next; tptr; tptr = next) {
180 if (tptr -> index != 0) {
181 result = (trace_type_record
183 strlen (tptr -> name), file, line));
184 if (result != ISC_R_SUCCESS)
190 return ISC_R_SUCCESS;
194 const char *buf,
const char *file,
int line)
205 const char *file,
int line)
218 log_error (
"%s(%d): trace_write_packet with null trace type",
219 file ? file :
"<unknown file>", line);
223 log_error (
"%s(%d): trace_write_packet with no tracefile.",
224 file ? file :
"<unknown file>", line);
230 for (i = 0; i < count; i++)
231 length += iov [i].len;
235 memset(&tmp, 0,
sizeof(tmp));
237 tmp.
when = htonl (time ((time_t *)0));
238 tmp.
length = htonl (length);
240 status = write (traceoutfile, &tmp,
sizeof tmp);
242 log_error (
"%s(%d): trace_write_packet write failed: %m",
244 return ISC_R_UNEXPECTED;
245 }
else if (status !=
sizeof tmp) {
246 log_error (
"%s(%d): trace_write_packet: short write (%d:%ld)",
247 file, line, status, (
long)(
sizeof tmp));
251 for (i = 0; i < count; i++) {
252 status = write (traceoutfile, iov [i].buf, iov [i].len);
254 log_error (
"%s(%d): %s write failed: %m",
255 file, line,
"trace_write_packet");
256 return ISC_R_UNEXPECTED;
257 }
else if (status != iov [i].len) {
258 log_error (
"%s(%d): %s: short write (%d:%d)",
260 "trace_write_packet", status, length);
269 static char zero [] = { 0, 0, 0, 0, 0, 0, 0 };
270 unsigned padl = 8 - (length % 8);
272 status = write (traceoutfile, zero, padl);
274 log_error (
"%s(%d): trace_write_packet write failed: %m",
276 return ISC_R_UNEXPECTED;
277 }
else if (status != padl) {
278 log_error (
"%s(%d): trace_write_packet: short write (%d:%d)",
279 file, line, status, padl);
284 return ISC_R_SUCCESS;
291 if (trace_type_max <= tptr -> index) {
292 delta = tptr -> index - trace_type_max + 10;
293 vec =
dmalloc (((trace_type_max + delta) *
297 memset (&vec [trace_type_max], 0,
299 trace_type_max += delta;
301 memcpy (vec, trace_types,
307 trace_types [tptr -> index] = tptr;
308 if (tptr -> index >= trace_type_count)
309 trace_type_count = tptr -> index + 1;
317 const char *file,
int line)
320 unsigned slen = strlen (name);
323 ttmp =
dmalloc (
sizeof *ttmp, file, line);
327 ttmp -> name =
dmalloc (slen + 1, file, line);
329 dfree (ttmp, file, line);
332 strcpy (ttmp -> name, name);
333 ttmp -> have_packet = have_packet;
334 ttmp -> stop_tracing = stop_tracing;
337 status = trace_type_record (ttmp, slen, file, line);
338 if (status != ISC_R_SUCCESS) {
339 dfree (ttmp -> name, file, line);
340 dfree (ttmp, file, line);
344 ttmp -> next = new_trace_types;
345 new_trace_types = ttmp;
351 static isc_result_t trace_type_record (
trace_type_t *ttmp,
unsigned slen,
352 const char *file,
int line)
359 return ISC_R_NOMEMORY;
360 ttmp -> index = ++traceindex;
362 tim -> index = htonl (ttmp -> index);
363 memcpy (tim -> name, ttmp -> name, slen);
366 (
char *)tim, file, line);
367 dfree (tim, file, line);
377 for (i = 0; i < trace_type_count; i++)
378 if (trace_types [i] -> stop_tracing)
379 (*(trace_types [i] -> stop_tracing))
396 prev = &new_trace_types;
397 for (tptr = new_trace_types; tptr; tptr = tptr -> next) {
398 len = strlen (tptr -> name);
400 !memcmp (tptr -> name, tmap -> name, len)) {
401 tptr -> index = ntohl (tmap -> index);
403 *prev = tptr -> next;
406 prev = &tptr -> next;
409 log_error (
"No registered trace type for type name %.*s",
418 trace_playback_flag = 1;
432 traceinfile = fopen (filename,
"re");
434 log_error(
"Can't open tracefile %s: %m", filename);
437 #if defined (HAVE_SETFD) 438 if (fcntl (fileno(traceinfile), F_SETFD, 1) < 0)
439 log_error(
"Can't set close-on-exec on %s: %m", filename);
441 status = fread(&tracefile_header, 1,
442 sizeof tracefile_header, traceinfile);
443 if (status <
sizeof tracefile_header) {
444 if (ferror(traceinfile))
445 log_error(
"Error reading trace file header: %m");
447 log_error(
"Short read on trace file header: %d %ld.",
448 status, (
long)(
sizeof tracefile_header));
451 tracefile_header.
magic = ntohl(tracefile_header.
magic);
453 tracefile_header.
hlen = ntohl(tracefile_header.
hlen);
454 tracefile_header.
phlen = ntohl(tracefile_header.
phlen);
457 log_error(
"%s: not a dhcp trace file.", filename);
461 log_error (
"tracefile version %ld > current %ld.",
462 (
long int)tracefile_header.
version,
466 if (tracefile_header.
phlen <
sizeof *tpkt) {
467 log_error(
"tracefile packet size too small - %ld < %ld",
468 (
long int)tracefile_header.
phlen,
469 (
long int)
sizeof *tpkt);
472 len = (
sizeof tracefile_header) - tracefile_header.
hlen;
474 log_error(
"tracefile header size too small - %ld < %ld",
475 (
long int)tracefile_header.
hlen,
476 (
long int)
sizeof tracefile_header);
480 status = fseek(traceinfile, (
long)len, SEEK_CUR);
489 log_error (
"can't allocate trace packet header.");
494 &bufmax)) == ISC_R_SUCCESS) {
512 char **buf,
unsigned *buflen,
517 int status, curposok = 0;
522 status = fgetpos(traceinfile, &curpos);
524 log_error(
"Can't save tracefile position: %m");
529 status = fread(tpkt, 1, (
size_t)tracefile_header.
phlen,
531 if (status < tracefile_header.
phlen) {
532 if (ferror(traceinfile))
533 log_error(
"Error reading trace packet header: " 535 else if (status == 0)
538 log_error (
"Short read on trace packet header:" 541 (
long int)tracefile_header.
phlen);
547 tpkt->
length = ntohl(tpkt -> length);
548 tpkt->
when = ntohl(tpkt -> when);
555 log_error (
"Trace packet with unknown index %ld",
572 if ((ttp != NULL) && (*ttp == NULL) &&
574 (trace_set_time_hook != NULL)) {
581 status = fsetpos(traceinfile, &curpos);
583 log_error(
"fsetpos in tracefile failed: %m");
587 (*trace_set_time_hook) (tpkt->
when);
595 if (ttp && *ttp && ttype != *ttp) {
596 log_error (
"Read packet type %s when expecting %s",
597 ttype -> name, (*ttp) -> name);
598 status = fsetpos (traceinfile, &curpos);
600 log_error (
"fsetpos in tracefile failed: %m");
603 return ISC_R_UNEXPECTEDTOKEN;
606 paylen = tpkt -> length;
608 paylen += 8 - (tpkt -> length % 8);
609 if (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;
636 return ISC_R_SUCCESS;
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;
693 if (result != ISC_R_SUCCESS) {
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;
715 return ISC_R_SUCCESS;
#define DHCP_R_PROTOCOLERROR
#define TRACEFILE_VERSION
void * dmalloc(unsigned, const char *, int)
#define DHCP_R_INVALIDARG
isc_result_t trace_write_packet_iov(trace_type_t *, int, trace_iov_t *, const char *, int)
int log_error(const char *,...) __attribute__((__format__(__printf__
trace_type_t * trace_type_register(const char *, void *, void(*)(trace_type_t *, unsigned, char *), void(*)(trace_type_t *), const char *, int)
isc_result_t trace_get_next_packet(trace_type_t **, tracepacket_t *, char **, unsigned *, unsigned *)
void(* have_packet)(trace_type_t *, unsigned, char *)
void trace_free_all(void)
void trace_file_replay(const char *)
isc_result_t trace_begin(const char *, const char *, int)
void dfree(void *, const char *, int)
void trace_index_map_input(trace_type_t *, unsigned, char *)
void trace_replay_init(void)
isc_result_t trace_init(void(*set_time)(time_t), const char *, int)
isc_result_t trace_get_packet(trace_type_t **, unsigned *, char **)
void trace_type_stash(trace_type_t *)
isc_result_t trace_get_file(trace_type_t *, const char *, unsigned *, char **)
isc_result_t trace_write_packet(trace_type_t *, unsigned, const char *, const char *, int)
#define TRACE_INDEX_MAPPING_SIZE
void trace_index_stop_tracing(trace_type_t *)
isc_result_t omapi_array_free(omapi_array_t **, const char *, int)