Annotation of embedaddon/dhcp/omapip/trace.c, revision 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>