Annotation of embedaddon/dhcp/omapip/trace.c, revision 1.1.1.1
1.1 misho 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-2007,2009 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: * https://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 https://www.isc.org/. To
32: * learn more about Nominum, Inc., see ``http://www.nominum.com''.
33: */
34:
35: #include "dhcpd.h"
36: #include <omapip/omapip_p.h>
37: #include <errno.h>
38:
39: #if defined (TRACING)
40: void (*trace_set_time_hook) (TIME);
41: static int tracing_stopped;
42: static int traceoutfile;
43: static int traceindex;
44: static trace_type_t **trace_types;
45: static int trace_type_count;
46: static int trace_type_max;
47: static trace_type_t *new_trace_types;
48: static FILE *traceinfile;
49: static tracefile_header_t tracefile_header;
50: static int trace_playback_flag;
51: trace_type_t trace_time_marker;
52:
53: #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
54: extern omapi_array_t *trace_listeners;
55: extern omapi_array_t *omapi_connections;
56:
57: extern int errno;
58:
59: void trace_free_all ()
60: {
61: trace_type_t *tp;
62: int i;
63: tp = new_trace_types;
64: while (tp) {
65: new_trace_types = tp -> next;
66: if (tp -> name) {
67: dfree (tp -> name, MDL);
68: tp -> name = (char *)0;
69: }
70: dfree (tp, MDL);
71: tp = new_trace_types;
72: }
73: for (i = 0; i < trace_type_count; i++) {
74: if (trace_types [i]) {
75: if (trace_types [i] -> name)
76: dfree (trace_types [i] -> name, MDL);
77: dfree (trace_types [i], MDL);
78: }
79: }
80: dfree (trace_types, MDL);
81: trace_types = (trace_type_t **)0;
82: trace_type_count = trace_type_max = 0;
83:
84: omapi_array_free (&trace_listeners, MDL);
85: omapi_array_free (&omapi_connections, MDL);
86: }
87: #endif
88:
89: static isc_result_t trace_type_record (trace_type_t *,
90: unsigned, const char *, int);
91:
92: int trace_playback ()
93: {
94: return trace_playback_flag;
95: }
96:
97: int trace_record ()
98: {
99: if (traceoutfile && !tracing_stopped)
100: return 1;
101: return 0;
102: }
103:
104: isc_result_t trace_init (void (*set_time) (TIME),
105: const char *file, int line)
106: {
107: trace_type_t *root_type;
108: static int root_setup = 0;
109:
110: if (root_setup)
111: return ISC_R_SUCCESS;
112:
113: trace_set_time_hook = set_time;
114:
115: root_type = trace_type_register ("trace-index-mapping",
116: (void *)0, trace_index_map_input,
117: trace_index_stop_tracing, file, line);
118: if (!root_type)
119: return ISC_R_UNEXPECTED;
120: if (new_trace_types == root_type)
121: new_trace_types = new_trace_types -> next;
122: root_type -> index = 0;
123: trace_type_stash (root_type);
124:
125: root_setup = 1;
126: return ISC_R_SUCCESS;
127: }
128:
129: isc_result_t trace_begin (const char *filename,
130: const char *file, int line)
131: {
132: tracefile_header_t tfh;
133: int status;
134: trace_type_t *tptr, *next;
135: isc_result_t result;
136:
137: if (traceoutfile) {
138: log_error ("%s(%d): trace_begin called twice",
139: file, line);
140: return ISC_R_INVALIDARG;
141: }
142:
143: traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL, 0600);
144: if (traceoutfile < 0 && errno == EEXIST) {
145: log_error ("WARNING: Overwriting trace file \"%s\"", filename);
146: traceoutfile = open (filename, O_WRONLY | O_EXCL, 0600);
147: }
148:
149: if (traceoutfile < 0) {
150: log_error ("%s(%d): trace_begin: %s: %m",
151: file, line, filename);
152: return ISC_R_UNEXPECTED;
153: }
154: #if defined (HAVE_SETFD)
155: if (fcntl (traceoutfile, F_SETFD, 1) < 0)
156: log_error ("Can't set close-on-exec on %s: %m", filename);
157: #endif
158:
159: tfh.magic = htonl (TRACEFILE_MAGIC);
160: tfh.version = htonl (TRACEFILE_VERSION);
161: tfh.hlen = htonl (sizeof (tracefile_header_t));
162: tfh.phlen = htonl (sizeof (tracepacket_t));
163:
164: status = write (traceoutfile, &tfh, sizeof tfh);
165: if (status < 0) {
166: log_error ("%s(%d): trace_begin write failed: %m", file, line);
167: return ISC_R_UNEXPECTED;
168: } else if (status != sizeof tfh) {
169: log_error ("%s(%d): trace_begin: short write (%d:%ld)",
170: file, line, status, (long)(sizeof tfh));
171: trace_stop ();
172: return ISC_R_UNEXPECTED;
173: }
174:
175: /* Stash all the types that have already been set up. */
176: if (new_trace_types) {
177: next = new_trace_types;
178: new_trace_types = (trace_type_t *)0;
179: for (tptr = next; tptr; tptr = next) {
180: next = tptr -> next;
181: if (tptr -> index != 0) {
182: result = (trace_type_record
183: (tptr,
184: strlen (tptr -> name), file, line));
185: if (result != ISC_R_SUCCESS)
186: return status;
187: }
188: }
189: }
190:
191: return ISC_R_SUCCESS;
192: }
193:
194: isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length,
195: const char *buf, const char *file, int line)
196: {
197: trace_iov_t iov;
198:
199: iov.buf = buf;
200: iov.len = length;
201: return trace_write_packet_iov (ttype, 1, &iov, file, line);
202: }
203:
204: isc_result_t trace_write_packet_iov (trace_type_t *ttype,
205: int count, trace_iov_t *iov,
206: const char *file, int line)
207: {
208: tracepacket_t tmp;
209: int status;
210: int i;
211: int length;
212:
213: /* Really shouldn't get called here, but it may be hard to turn off
214: tracing midstream if the trace file write fails or something. */
215: if (tracing_stopped)
216: return 0;
217:
218: if (!ttype) {
219: log_error ("%s(%d): trace_write_packet with null trace type",
220: file ? file : "<unknown file>", line);
221: return ISC_R_INVALIDARG;
222: }
223: if (!traceoutfile) {
224: log_error ("%s(%d): trace_write_packet with no tracefile.",
225: file ? file : "<unknown file>", line);
226: return ISC_R_INVALIDARG;
227: }
228:
229: /* Compute the total length of the iov. */
230: length = 0;
231: for (i = 0; i < count; i++)
232: length += iov [i].len;
233:
234: /* We have to swap out the data, because it may be read back on a
235: machine of different endianness. */
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: {
354: trace_index_mapping_t *tim;
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],
365: slen + TRACE_INDEX_MAPPING_SIZE,
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 = (tracepacket_t *)0;
424: int status;
425: char *buf = (char *)0;
426: unsigned buflen;
427: unsigned bufmax = 0;
428: trace_type_t *ttype = (trace_type_t *)0;
429: isc_result_t result;
430: int len;
431:
432: traceinfile = fopen (filename, "r");
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) {
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 = (trace_type_t *)0;
497: }
498: out:
499: fclose (traceinfile);
500: if (buf)
501: dfree (buf, MDL);
502: if (tpkt)
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;
518: fpos_t curpos;
519:
520: status = fgetpos (traceinfile, &curpos);
521: if (status < 0)
522: log_error ("Can't save tracefile position: %m");
523:
524: status = fread (tpkt, 1, (size_t)tracefile_header.phlen, traceinfile);
525: if (status < tracefile_header.phlen) {
526: if (ferror (traceinfile))
527: log_error ("Error reading trace packet header: %m");
528: else if (status == 0)
529: return ISC_R_EOF;
530: else
531: log_error ("Short read on trace packet header: "
532: "%ld %ld.",
533: (long int)status,
534: (long int)tracefile_header.phlen);
535: return ISC_R_PROTOCOLERROR;
536: }
537:
538: /* Swap the packet. */
539: tpkt -> type_index = ntohl (tpkt -> type_index);
540: tpkt -> length = ntohl (tpkt -> length);
541: tpkt -> when = ntohl (tpkt -> when);
542:
543: /* See if there's a handler for this packet type. */
544: if (tpkt -> type_index < trace_type_count &&
545: trace_types [tpkt -> type_index])
546: ttype = trace_types [tpkt -> type_index];
547: else {
548: log_error ("Trace packet with unknown index %ld",
549: (long int)tpkt -> type_index);
550: return ISC_R_PROTOCOLERROR;
551: }
552:
553: /* If we were just hunting for the time marker, we've found it,
554: so back up to the beginning of the packet and return its
555: type. */
556: if (ttp && *ttp == &trace_time_marker) {
557: *ttp = ttype;
558: status = fsetpos (traceinfile, &curpos);
559: if (status < 0) {
560: log_error ("fsetpos in tracefile failed: %m");
561: return ISC_R_PROTOCOLERROR;
562: }
563: return ISC_R_EXISTS;
564: }
565:
566: /* If we were supposed to get a particular kind of packet,
567: check to see that we got the right kind. */
568: if (ttp && *ttp && ttype != *ttp) {
569: log_error ("Read packet type %s when expecting %s",
570: ttype -> name, (*ttp) -> name);
571: status = fsetpos (traceinfile, &curpos);
572: if (status < 0) {
573: log_error ("fsetpos in tracefile failed: %m");
574: return ISC_R_PROTOCOLERROR;
575: }
576: return ISC_R_UNEXPECTEDTOKEN;
577: }
578:
579: paylen = tpkt -> length;
580: if (paylen % 8)
581: paylen += 8 - (tpkt -> length % 8);
582: if (paylen > (*bufmax)) {
583: if ((*buf))
584: dfree ((*buf), MDL);
585: (*bufmax) = ((paylen + 1023) & ~1023U);
586: (*buf) = dmalloc ((*bufmax), MDL);
587: if (!(*buf)) {
588: log_error ("Can't allocate input buffer sized %d",
589: (*bufmax));
590: return ISC_R_NOMEMORY;
591: }
592: }
593:
594: status = fread ((*buf), 1, paylen, traceinfile);
595: if (status < paylen) {
596: if (ferror (traceinfile))
597: log_error ("Error reading trace payload: %m");
598: else
599: log_error ("Short read on trace payload: %d %d.",
600: status, paylen);
601: return ISC_R_PROTOCOLERROR;
602: }
603:
604: /* Store the actual length of the payload. */
605: *buflen = tpkt -> length;
606:
607: if (trace_set_time_hook)
608: (*trace_set_time_hook) (tpkt -> when);
609:
610: if (ttp)
611: *ttp = ttype;
612: return ISC_R_SUCCESS;
613: }
614:
615: isc_result_t trace_get_packet (trace_type_t **ttp,
616: unsigned *buflen, char **buf)
617: {
618: tracepacket_t *tpkt;
619: unsigned bufmax = 0;
620: isc_result_t status;
621:
622: if (!buf || *buf)
623: return ISC_R_INVALIDARG;
624:
625: tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
626: if (!tpkt) {
627: log_error ("can't allocate trace packet header.");
628: return ISC_R_NOMEMORY;
629: }
630:
631: status = trace_get_next_packet (ttp, tpkt, buf, buflen, &bufmax);
632:
633: dfree (tpkt, MDL);
634: return status;
635: }
636:
637: time_t trace_snoop_time (trace_type_t **ptp)
638: {
639: tracepacket_t *tpkt;
640: unsigned bufmax = 0;
641: unsigned buflen = 0;
642: char *buf = (char *)0;
643: time_t result;
644: trace_type_t *ttp;
645:
646: if (!ptp)
647: ptp = &ttp;
648:
649: tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
650: if (!tpkt) {
651: log_error ("can't allocate trace packet header.");
652: return ISC_R_NOMEMORY;
653: }
654:
655: *ptp = &trace_time_marker;
656: trace_get_next_packet (ptp, tpkt, &buf, &buflen, &bufmax);
657: result = tpkt -> when;
658:
659: dfree (tpkt, MDL);
660: return result;
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 ISC_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: if (result != ISC_R_SUCCESS) {
694: dfree (tpkt, MDL);
695: if (*buf)
696: dfree (*buf, MDL);
697: return result;
698: }
699:
700: /* Make sure the filename is right. */
701: if (strcmp (filename, *buf)) {
702: log_error ("Read file %s when expecting %s", *buf, filename);
703: status = fsetpos (traceinfile, &curpos);
704: if (status < 0) {
705: log_error ("fsetpos in tracefile failed: %m");
706: dfree (tpkt, MDL);
707: dfree (*buf, MDL);
708: return ISC_R_PROTOCOLERROR;
709: }
710: return ISC_R_UNEXPECTEDTOKEN;
711: }
712:
713: dfree (tpkt, MDL);
714: return ISC_R_SUCCESS;
715: }
716: #endif /* TRACING */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>