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