]> git.ipfire.org Git - thirdparty/dhcp.git/blame - omapip/trace.c
- Merge changes between 3.0.3RC1 and 3.0.4-BETA-3 into HEAD (silence
[thirdparty/dhcp.git] / omapip / trace.c
CommitLineData
c128c100
TL
1/* trace.c
2
ac679e8f
TL
3 Subroutines that support tracing of OMAPI wire transactions and
4 provide a mechanism for programs using OMAPI to trace their own
5 transactions... */
c128c100
TL
6
7/*
88cd8aca 8 * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
98311e4b 9 * Copyright (c) 2001-2003 by Internet Software Consortium
c128c100 10 *
98311e4b
DH
11 * Permission to use, copy, modify, and distribute this software for any
12 * purpose with or without fee is hereby granted, provided that the above
13 * copyright notice and this permission notice appear in all copies.
c128c100 14 *
98311e4b
DH
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.
c128c100 22 *
98311e4b
DH
23 * Internet Systems Consortium, Inc.
24 * 950 Charter Street
25 * Redwood City, CA 94063
26 * <info@isc.org>
27 * http://www.isc.org/
c128c100 28 *
98311e4b 29 * This software has been written for Internet Systems Consortium
c128c100 30 * by Ted Lemon, as part of a project for Nominum, Inc. To learn more
98311e4b 31 * about Internet Systems Consortium, see http://www.isc.org/. To
c128c100
TL
32 * learn more about Nominum, Inc., see ``http://www.nominum.com''.
33 */
34
88cd8aca
DH
35#ifndef lint
36static char ocopyright[] =
37"$Id: trace.c,v 1.12 2006/02/24 23:16:30 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
38#endif
39
c128c100
TL
40#include <omapip/omapip_p.h>
41
42#if defined (TRACING)
88cd8aca 43void (*trace_set_time_hook) (TIME);
c128c100
TL
44static int tracing_stopped;
45static int traceoutfile;
46static int traceindex;
47static trace_type_t **trace_types;
48static int trace_type_count;
49static int trace_type_max;
50static trace_type_t *new_trace_types;
51static FILE *traceinfile;
52static tracefile_header_t tracefile_header;
53static int trace_playback_flag;
ac679e8f 54trace_type_t trace_time_marker;
c128c100 55
d758ad8c
TL
56#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
57extern omapi_array_t *trace_listeners;
58extern omapi_array_t *omapi_connections;
59
60void trace_free_all ()
61{
62 trace_type_t *tp;
63 int i;
64 tp = new_trace_types;
65 while (tp) {
66 new_trace_types = tp -> next;
67 if (tp -> name) {
68 dfree (tp -> name, MDL);
69 tp -> name = (char *)0;
70 }
71 dfree (tp, MDL);
72 tp = new_trace_types;
73 }
74 for (i = 0; i < trace_type_count; i++) {
75 if (trace_types [i]) {
76 if (trace_types [i] -> name)
77 dfree (trace_types [i] -> name, MDL);
78 dfree (trace_types [i], MDL);
79 }
80 }
81 dfree (trace_types, MDL);
82 trace_types = (trace_type_t **)0;
83 trace_type_count = trace_type_max = 0;
84
85 omapi_array_free (&trace_listeners, MDL);
86 omapi_array_free (&omapi_connections, MDL);
87}
88#endif
89
7a563fb8
TL
90static isc_result_t trace_type_record (trace_type_t *,
91 unsigned, const char *, int);
92
c128c100
TL
93int trace_playback ()
94{
95 return trace_playback_flag;
96}
97
98int trace_record ()
99{
3a4f23b5 100 if (traceoutfile && !tracing_stopped)
c128c100
TL
101 return 1;
102 return 0;
103}
104
88cd8aca 105isc_result_t trace_init (void (*set_time) (TIME),
c128c100
TL
106 const char *file, int line)
107{
108 trace_type_t *root_type;
109 static int root_setup = 0;
110
111 if (root_setup)
112 return ISC_R_SUCCESS;
113
114 trace_set_time_hook = set_time;
115
116 root_type = trace_type_register ("trace-index-mapping",
117 (void *)0, trace_index_map_input,
118 trace_index_stop_tracing, file, line);
119 if (!root_type)
120 return ISC_R_UNEXPECTED;
d758ad8c
TL
121 if (new_trace_types == root_type)
122 new_trace_types = new_trace_types -> next;
c128c100
TL
123 root_type -> index = 0;
124 trace_type_stash (root_type);
125
126 root_setup = 1;
127 return ISC_R_SUCCESS;
128}
129
130isc_result_t trace_begin (const char *filename,
131 const char *file, int line)
132{
133 tracefile_header_t tfh;
134 int status;
7a563fb8
TL
135 trace_type_t *tptr, *next;
136 isc_result_t result;
c128c100
TL
137
138 if (traceoutfile) {
139 log_error ("%s(%d): trace_begin called twice",
140 file, line);
141 return ISC_R_INVALIDARG;
142 }
143
88cd8aca 144 traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL, 0600);
c128c100
TL
145 if (traceoutfile < 0) {
146 log_error ("%s(%d): trace_begin: %s: %m",
147 file, line, filename);
148 return ISC_R_UNEXPECTED;
149 }
150#if defined (HAVE_SETFD)
151 if (fcntl (traceoutfile, F_SETFD, 1) < 0)
152 log_error ("Can't set close-on-exec on %s: %m", filename);
153#endif
154
155 tfh.magic = htonl (TRACEFILE_MAGIC);
156 tfh.version = htonl (TRACEFILE_VERSION);
157 tfh.hlen = htonl (sizeof (tracefile_header_t));
158 tfh.phlen = htonl (sizeof (tracepacket_t));
159
160 status = write (traceoutfile, &tfh, sizeof tfh);
161 if (status < 0) {
162 log_error ("%s(%d): trace_begin write failed: %m", file, line);
163 return ISC_R_UNEXPECTED;
164 } else if (status != sizeof tfh) {
c4661845
TL
165 log_error ("%s(%d): trace_begin: short write (%d:%ld)",
166 file, line, status, (long)(sizeof tfh));
c128c100 167 trace_stop ();
7a563fb8
TL
168 return ISC_R_UNEXPECTED;
169 }
170
171 /* Stash all the types that have already been set up. */
172 if (new_trace_types) {
173 next = new_trace_types;
174 new_trace_types = (trace_type_t *)0;
175 for (tptr = next; tptr; tptr = next) {
176 next = tptr -> next;
177 if (tptr -> index != 0) {
178 result = (trace_type_record
179 (tptr,
180 strlen (tptr -> name), file, line));
181 if (result != ISC_R_SUCCESS)
182 return status;
183 }
184 }
c128c100 185 }
7a563fb8 186
c128c100
TL
187 return ISC_R_SUCCESS;
188}
189
190isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length,
191 const char *buf, const char *file, int line)
192{
193 trace_iov_t iov;
194
195 iov.buf = buf;
196 iov.len = length;
197 return trace_write_packet_iov (ttype, 1, &iov, file, line);
198}
199
200isc_result_t trace_write_packet_iov (trace_type_t *ttype,
201 int count, trace_iov_t *iov,
202 const char *file, int line)
203{
204 tracepacket_t tmp;
205 int status;
206 int i;
207 int length;
208
209 /* Really shouldn't get called here, but it may be hard to turn off
210 tracing midstream if the trace file write fails or something. */
211 if (tracing_stopped)
212 return 0;
213
214 if (!ttype) {
215 log_error ("%s(%d): trace_write_packet with null trace type",
216 file ? file : "<unknown file>", line);
217 return ISC_R_INVALIDARG;
218 }
219 if (!traceoutfile) {
220 log_error ("%s(%d): trace_write_packet with no tracefile.",
221 file ? file : "<unknown file>", line);
222 return ISC_R_INVALIDARG;
223 }
224
225 /* Compute the total length of the iov. */
226 length = 0;
227 for (i = 0; i < count; i++)
228 length += iov [i].len;
229
230 /* We have to swap out the data, because it may be read back on a
231 machine of different endianness. */
232 tmp.type_index = htonl (ttype -> index);
233 tmp.when = htonl (time ((time_t *)0)); /* XXX */
234 tmp.length = htonl (length);
235
236 status = write (traceoutfile, &tmp, sizeof tmp);
237 if (status < 0) {
238 log_error ("%s(%d): trace_write_packet write failed: %m",
239 file, line);
240 return ISC_R_UNEXPECTED;
241 } else if (status != sizeof tmp) {
c4661845
TL
242 log_error ("%s(%d): trace_write_packet: short write (%d:%ld)",
243 file, line, status, (long)(sizeof tmp));
c128c100
TL
244 trace_stop ();
245 }
246
247 for (i = 0; i < count; i++) {
248 status = write (traceoutfile, iov [i].buf, iov [i].len);
249 if (status < 0) {
250 log_error ("%s(%d): %s write failed: %m",
251 file, line, "trace_write_packet");
252 return ISC_R_UNEXPECTED;
253 } else if (status != iov [i].len) {
254 log_error ("%s(%d): %s: short write (%d:%d)",
255 file, line,
256 "trace_write_packet", status, length);
257 trace_stop ();
258 }
259 }
260
261 /* Write padding on the end of the packet to align the next
262 packet to an 8-byte boundary. This is in case we decide to
263 use mmap in some clever way later on. */
264 if (length % 8) {
265 static char zero [] = { 0, 0, 0, 0, 0, 0, 0 };
266 unsigned padl = 8 - (length % 8);
267
268 status = write (traceoutfile, zero, padl);
269 if (status < 0) {
270 log_error ("%s(%d): trace_write_packet write failed: %m",
271 file, line);
272 return ISC_R_UNEXPECTED;
273 } else if (status != padl) {
274 log_error ("%s(%d): trace_write_packet: short write (%d:%d)",
275 file, line, status, padl);
276 trace_stop ();
277 }
278 }
279
280 return ISC_R_SUCCESS;
281}
282
283void trace_type_stash (trace_type_t *tptr)
284{
285 trace_type_t **vec;
286 int delta;
287 if (trace_type_max <= tptr -> index) {
288 delta = tptr -> index - trace_type_max + 10;
289 vec = dmalloc (((trace_type_max + delta) *
290 sizeof (trace_type_t *)), MDL);
291 if (!vec)
292 return;
293 memset (&vec [trace_type_max], 0,
294 (sizeof (trace_type_t *)) * delta);
295 trace_type_max += delta;
296 if (trace_types) {
297 memcpy (vec, trace_types,
298 trace_type_count * sizeof (trace_type_t *));
299 dfree (trace_types, MDL);
300 }
301 trace_types = vec;
302 }
303 trace_types [tptr -> index] = tptr;
304 if (tptr -> index >= trace_type_count)
305 trace_type_count = tptr -> index + 1;
306}
307
308trace_type_t *trace_type_register (const char *name,
309 void *baggage,
310 void (*have_packet) (trace_type_t *,
311 unsigned, char *),
312 void (*stop_tracing) (trace_type_t *),
313 const char *file, int line)
314{
315 trace_type_t *ttmp, *tptr;
c128c100 316 unsigned slen = strlen (name);
7a563fb8 317 isc_result_t status;
c128c100
TL
318
319 ttmp = dmalloc (sizeof *ttmp, file, line);
7a563fb8 320 if (!ttmp)
c128c100 321 return ttmp;
7a563fb8 322 ttmp -> index = -1;
c128c100
TL
323 ttmp -> name = dmalloc (slen + 1, file, line);
324 if (!ttmp -> name) {
325 dfree (ttmp, file, line);
326 return (trace_type_t *)0;
327 }
328 strcpy (ttmp -> name, name);
329 ttmp -> have_packet = have_packet;
330 ttmp -> stop_tracing = stop_tracing;
331
c128c100 332 if (traceoutfile) {
7a563fb8
TL
333 status = trace_type_record (ttmp, slen, file, line);
334 if (status != ISC_R_SUCCESS) {
c128c100
TL
335 dfree (ttmp -> name, file, line);
336 dfree (ttmp, file, line);
7a563fb8 337 return (trace_type_t *)0;
c128c100 338 }
7a563fb8
TL
339 } else {
340 ttmp -> next = new_trace_types;
341 new_trace_types = ttmp;
c128c100
TL
342 }
343
344 return ttmp;
345}
346
7a563fb8
TL
347static isc_result_t trace_type_record (trace_type_t *ttmp, unsigned slen,
348 const char *file, int line)
349{
350 trace_index_mapping_t *tim;
351 isc_result_t status;
352
353 tim = dmalloc (slen + TRACE_INDEX_MAPPING_SIZE, file, line);
354 if (!tim)
355 return ISC_R_NOMEMORY;
356 ttmp -> index = ++traceindex;
357 trace_type_stash (ttmp);
358 tim -> index = htonl (ttmp -> index);
359 memcpy (tim -> name, ttmp -> name, slen);
360 status = trace_write_packet (trace_types [0],
361 slen + TRACE_INDEX_MAPPING_SIZE,
362 (char *)tim, file, line);
363 dfree (tim, file, line);
364 return status;
365}
366
c128c100
TL
367/* Stop all registered trace types from trying to trace. */
368
369void trace_stop (void)
370{
371 int i;
372
373 for (i = 0; i < trace_type_count; i++)
374 if (trace_types [i] -> stop_tracing)
375 (*(trace_types [i] -> stop_tracing))
376 (trace_types [i]);
377 tracing_stopped = 1;
378}
379
380void trace_index_map_input (trace_type_t *ttype, unsigned length, char *buf)
381{
382 trace_index_mapping_t *tmap;
383 unsigned len;
384 trace_type_t *tptr, **prev;
385
386 if (length < TRACE_INDEX_MAPPING_SIZE) {
387 log_error ("short trace index mapping");
388 return;
389 }
390 tmap = (trace_index_mapping_t *)buf;
391
392 prev = &new_trace_types;
393 for (tptr = new_trace_types; tptr; tptr = tptr -> next) {
394 len = strlen (tptr -> name);
395 if (len == length - TRACE_INDEX_MAPPING_SIZE &&
396 !memcmp (tptr -> name, tmap -> name, len)) {
397 tptr -> index = ntohl (tmap -> index);
398 trace_type_stash (tptr);
399 *prev = tptr -> next;
400 return;
401 }
402 prev = &tptr -> next;
403 }
404
405 log_error ("No registered trace type for type name %.*s",
406 (int)length - TRACE_INDEX_MAPPING_SIZE, tmap -> name);
407 return;
408}
409
410void trace_index_stop_tracing (trace_type_t *ttype) { }
411
412void trace_replay_init (void)
413{
414 trace_playback_flag = 1;
415}
416
417void trace_file_replay (const char *filename)
418{
419 tracepacket_t *tpkt = (tracepacket_t *)0;
420 int status;
421 char *buf = (char *)0;
a7394d15 422 unsigned buflen;
c128c100
TL
423 unsigned bufmax = 0;
424 trace_type_t *ttype = (trace_type_t *)0;
425 isc_result_t result;
426 int len;
427
428 traceinfile = fopen (filename, "r");
429 if (!traceinfile) {
430 log_error ("Can't open tracefile %s: %m", filename);
431 return;
432 }
433#if defined (HAVE_SETFD)
434 if (fcntl (fileno (traceinfile), F_SETFD, 1) < 0)
435 log_error ("Can't set close-on-exec on %s: %m", filename);
436#endif
437 status = fread (&tracefile_header, 1,
438 sizeof tracefile_header, traceinfile);
439 if (status < sizeof tracefile_header) {
440 if (ferror (traceinfile))
441 log_error ("Error reading trace file header: %m");
442 else
c4661845
TL
443 log_error ("Short read on trace file header: %d %ld.",
444 status, (long)(sizeof tracefile_header));
c128c100
TL
445 goto out;
446 }
447 tracefile_header.magic = ntohl (tracefile_header.magic);
448 tracefile_header.version = ntohl (tracefile_header.version);
449 tracefile_header.hlen = ntohl (tracefile_header.hlen);
450 tracefile_header.phlen = ntohl (tracefile_header.phlen);
451
452 if (tracefile_header.magic != TRACEFILE_MAGIC) {
453 log_error ("%s: not a dhcp trace file.", filename);
454 goto out;
455 }
456 if (tracefile_header.version > TRACEFILE_VERSION) {
d0042425
DN
457 log_error ("tracefile version %ld > current %ld.",
458 (long int)tracefile_header.version,
459 (long int)TRACEFILE_VERSION);
c128c100
TL
460 goto out;
461 }
462 if (tracefile_header.phlen < sizeof *tpkt) {
d0042425
DN
463 log_error ("tracefile packet size too small - %ld < %ld",
464 (long int)tracefile_header.phlen,
465 (long int)sizeof *tpkt);
c128c100
TL
466 goto out;
467 }
468 len = (sizeof tracefile_header) - tracefile_header.hlen;
469 if (len < 0) {
d0042425
DN
470 log_error ("tracefile header size too small - %ld < %ld",
471 (long int)tracefile_header.hlen,
472 (long int)sizeof tracefile_header);
c128c100
TL
473 goto out;
474 }
475 if (len > 0) {
476 status = fseek (traceinfile, (long)len, SEEK_CUR);
477 if (status < 0) {
478 log_error ("can't seek past header: %m");
479 goto out;
480 }
481 }
482
483 tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
484 if (!tpkt) {
485 log_error ("can't allocate trace packet header.");
486 goto out;
487 }
488
489 while ((result = trace_get_next_packet (&ttype, tpkt, &buf, &buflen,
490 &bufmax)) == ISC_R_SUCCESS) {
491 (*ttype -> have_packet) (ttype, tpkt -> length, buf);
492 ttype = (trace_type_t *)0;
493 }
494 out:
495 fclose (traceinfile);
496 if (buf)
497 dfree (buf, MDL);
498 if (tpkt)
499 dfree (tpkt, MDL);
500}
501
502/* Get the next packet from the file. If ttp points to a nonzero pointer
503 to a trace type structure, check the next packet to see if it's of the
504 expected type, and back off if not. */
505
506isc_result_t trace_get_next_packet (trace_type_t **ttp,
507 tracepacket_t *tpkt,
508 char **buf, unsigned *buflen,
509 unsigned *bufmax)
510{
511 trace_type_t *ttype;
512 unsigned paylen;
513 int status;
514 int len;
515 fpos_t curpos;
516
517 status = fgetpos (traceinfile, &curpos);
518 if (status < 0)
519 log_error ("Can't save tracefile position: %m");
520
521 status = fread (tpkt, 1, (size_t)tracefile_header.phlen, traceinfile);
522 if (status < tracefile_header.phlen) {
523 if (ferror (traceinfile))
524 log_error ("Error reading trace packet header: %m");
525 else if (status == 0)
526 return ISC_R_EOF;
527 else
d0042425
DN
528 log_error ("Short read on trace packet header: "
529 "%ld %ld.",
530 (long int)status,
531 (long int)tracefile_header.phlen);
c128c100
TL
532 return ISC_R_PROTOCOLERROR;
533 }
534
535 /* Swap the packet. */
536 tpkt -> type_index = ntohl (tpkt -> type_index);
537 tpkt -> length = ntohl (tpkt -> length);
6b85636e 538 tpkt -> when = ntohl (tpkt -> when);
c128c100
TL
539
540 /* See if there's a handler for this packet type. */
541 if (tpkt -> type_index < trace_type_count &&
542 trace_types [tpkt -> type_index])
543 ttype = trace_types [tpkt -> type_index];
544 else {
d0042425
DN
545 log_error ("Trace packet with unknown index %ld",
546 (long int)tpkt -> type_index);
c128c100
TL
547 return ISC_R_PROTOCOLERROR;
548 }
549
6b85636e
TL
550 /* If we were just hunting for the time marker, we've found it,
551 so back up to the beginning of the packet and return its
552 type. */
553 if (ttp && *ttp == &trace_time_marker) {
554 *ttp = ttype;
555 status = fsetpos (traceinfile, &curpos);
556 if (status < 0) {
557 log_error ("fsetpos in tracefile failed: %m");
558 return ISC_R_PROTOCOLERROR;
559 }
560 return ISC_R_EXISTS;
561 }
562
c128c100
TL
563 /* If we were supposed to get a particular kind of packet,
564 check to see that we got the right kind. */
565 if (ttp && *ttp && ttype != *ttp) {
566 log_error ("Read packet type %s when expecting %s",
567 ttype -> name, (*ttp) -> name);
568 status = fsetpos (traceinfile, &curpos);
569 if (status < 0) {
570 log_error ("fsetpos in tracefile failed: %m");
571 return ISC_R_PROTOCOLERROR;
572 }
573 return ISC_R_UNEXPECTEDTOKEN;
574 }
575
576 paylen = tpkt -> length;
577 if (paylen % 8)
578 paylen += 8 - (tpkt -> length % 8);
579 if (paylen > (*bufmax)) {
580 if ((*buf))
581 dfree ((*buf), MDL);
582 (*bufmax) = ((paylen + 1023) & ~1023U);
583 (*buf) = dmalloc ((*bufmax), MDL);
584 if (!(*buf)) {
585 log_error ("Can't allocate input buffer sized %d",
586 (*bufmax));
587 return ISC_R_NOMEMORY;
588 }
589 }
590
591 status = fread ((*buf), 1, paylen, traceinfile);
592 if (status < paylen) {
593 if (ferror (traceinfile))
594 log_error ("Error reading trace payload: %m");
595 else
596 log_error ("Short read on trace payload: %d %d.",
597 status, paylen);
598 return ISC_R_PROTOCOLERROR;
599 }
600
601 /* Store the actual length of the payload. */
602 *buflen = tpkt -> length;
603
604 if (trace_set_time_hook)
605 (*trace_set_time_hook) (tpkt -> when);
606
607 if (ttp)
608 *ttp = ttype;
609 return ISC_R_SUCCESS;
610}
611
612isc_result_t trace_get_packet (trace_type_t **ttp,
613 unsigned *buflen, char **buf)
614{
615 tracepacket_t *tpkt;
616 unsigned bufmax = 0;
617 isc_result_t status;
618
619 if (!buf || *buf)
620 return ISC_R_INVALIDARG;
621
622 tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
623 if (!tpkt) {
624 log_error ("can't allocate trace packet header.");
625 return ISC_R_NOMEMORY;
626 }
627
628 status = trace_get_next_packet (ttp, tpkt, buf, buflen, &bufmax);
629
630 dfree (tpkt, MDL);
631 return status;
632}
633
6b85636e 634time_t trace_snoop_time (trace_type_t **ptp)
ac679e8f
TL
635{
636 tracepacket_t *tpkt;
637 unsigned bufmax = 0;
638 unsigned buflen = 0;
639 char *buf = (char *)0;
640 isc_result_t status;
641 time_t result;
6b85636e 642 trace_type_t *ttp;
ac679e8f 643
6b85636e
TL
644 if (!ptp)
645 ptp = &ttp;
ac679e8f
TL
646
647 tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
648 if (!tpkt) {
649 log_error ("can't allocate trace packet header.");
650 return ISC_R_NOMEMORY;
651 }
652
6b85636e
TL
653 *ptp = &trace_time_marker;
654 trace_get_next_packet (ptp, tpkt, &buf, &buflen, &bufmax);
ac679e8f
TL
655 result = tpkt -> when;
656
657 dfree (tpkt, MDL);
658 return result;
659}
660
c128c100
TL
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 ISC_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 if (result != ISC_R_SUCCESS) {
692 dfree (tpkt, MDL);
693 if (*buf)
694 dfree (*buf, MDL);
695 return result;
696 }
697
698 /* Make sure the filename is right. */
699 if (strcmp (filename, *buf)) {
700 log_error ("Read file %s when expecting %s", *buf, filename);
701 status = fsetpos (traceinfile, &curpos);
702 if (status < 0) {
703 log_error ("fsetpos in tracefile failed: %m");
704 dfree (tpkt, MDL);
705 dfree (*buf, MDL);
706 return ISC_R_PROTOCOLERROR;
707 }
708 return ISC_R_UNEXPECTEDTOKEN;
709 }
710
711 dfree (tpkt, MDL);
712 return ISC_R_SUCCESS;
713}
714#endif /* TRACING */