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