diff options
Diffstat (limited to 'contrib/isc-dhcp/omapip/trace.c')
-rw-r--r-- | contrib/isc-dhcp/omapip/trace.c | 709 |
1 files changed, 0 insertions, 709 deletions
diff --git a/contrib/isc-dhcp/omapip/trace.c b/contrib/isc-dhcp/omapip/trace.c deleted file mode 100644 index 9245d27..0000000 --- a/contrib/isc-dhcp/omapip/trace.c +++ /dev/null @@ -1,709 +0,0 @@ -/* trace.c - - Subroutines that support tracing of OMAPI wire transactions and - provide a mechanism for programs using OMAPI to trace their own - transactions... */ - -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 2001-2003 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Internet Systems Consortium, Inc. - * 950 Charter Street - * Redwood City, CA 94063 - * <info@isc.org> - * http://www.isc.org/ - * - * This software has been written for Internet Systems Consortium - * by Ted Lemon, as part of a project for Nominum, Inc. To learn more - * about Internet Systems Consortium, see http://www.isc.org/. To - * learn more about Nominum, Inc., see ``http://www.nominum.com''. - */ - -#include <omapip/omapip_p.h> - -#if defined (TRACING) -void (*trace_set_time_hook) (u_int32_t); -static int tracing_stopped; -static int traceoutfile; -static int traceindex; -static trace_type_t **trace_types; -static int trace_type_count; -static int trace_type_max; -static trace_type_t *new_trace_types; -static FILE *traceinfile; -static tracefile_header_t tracefile_header; -static int trace_playback_flag; -trace_type_t trace_time_marker; - -#if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT) -extern omapi_array_t *trace_listeners; -extern omapi_array_t *omapi_connections; - -void trace_free_all () -{ - trace_type_t *tp; - int i; - tp = new_trace_types; - while (tp) { - new_trace_types = tp -> next; - if (tp -> name) { - dfree (tp -> name, MDL); - tp -> name = (char *)0; - } - dfree (tp, MDL); - tp = new_trace_types; - } - for (i = 0; i < trace_type_count; i++) { - if (trace_types [i]) { - if (trace_types [i] -> name) - dfree (trace_types [i] -> name, MDL); - dfree (trace_types [i], MDL); - } - } - dfree (trace_types, MDL); - trace_types = (trace_type_t **)0; - trace_type_count = trace_type_max = 0; - - omapi_array_free (&trace_listeners, MDL); - omapi_array_free (&omapi_connections, MDL); -} -#endif - -static isc_result_t trace_type_record (trace_type_t *, - unsigned, const char *, int); - -int trace_playback () -{ - return trace_playback_flag; -} - -int trace_record () -{ - if (traceoutfile && !tracing_stopped) - return 1; - return 0; -} - -isc_result_t trace_init (void (*set_time) (u_int32_t), - const char *file, int line) -{ - trace_type_t *root_type; - static int root_setup = 0; - - if (root_setup) - return ISC_R_SUCCESS; - - trace_set_time_hook = set_time; - - root_type = trace_type_register ("trace-index-mapping", - (void *)0, trace_index_map_input, - trace_index_stop_tracing, file, line); - if (!root_type) - return ISC_R_UNEXPECTED; - if (new_trace_types == root_type) - new_trace_types = new_trace_types -> next; - root_type -> index = 0; - trace_type_stash (root_type); - - root_setup = 1; - return ISC_R_SUCCESS; -} - -isc_result_t trace_begin (const char *filename, - const char *file, int line) -{ - tracefile_header_t tfh; - int status; - trace_type_t *tptr, *next; - isc_result_t result; - - if (traceoutfile) { - log_error ("%s(%d): trace_begin called twice", - file, line); - return ISC_R_INVALIDARG; - } - - traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL, 0644); - if (traceoutfile < 0) { - log_error ("%s(%d): trace_begin: %s: %m", - file, line, filename); - return ISC_R_UNEXPECTED; - } -#if defined (HAVE_SETFD) - if (fcntl (traceoutfile, F_SETFD, 1) < 0) - log_error ("Can't set close-on-exec on %s: %m", filename); -#endif - - tfh.magic = htonl (TRACEFILE_MAGIC); - tfh.version = htonl (TRACEFILE_VERSION); - tfh.hlen = htonl (sizeof (tracefile_header_t)); - tfh.phlen = htonl (sizeof (tracepacket_t)); - - status = write (traceoutfile, &tfh, sizeof tfh); - if (status < 0) { - log_error ("%s(%d): trace_begin write failed: %m", file, line); - return ISC_R_UNEXPECTED; - } else if (status != sizeof tfh) { - log_error ("%s(%d): trace_begin: short write (%d:%ld)", - file, line, status, (long)(sizeof tfh)); - trace_stop (); - return ISC_R_UNEXPECTED; - } - - /* Stash all the types that have already been set up. */ - if (new_trace_types) { - next = new_trace_types; - new_trace_types = (trace_type_t *)0; - for (tptr = next; tptr; tptr = next) { - next = tptr -> next; - if (tptr -> index != 0) { - result = (trace_type_record - (tptr, - strlen (tptr -> name), file, line)); - if (result != ISC_R_SUCCESS) - return status; - } - } - } - - return ISC_R_SUCCESS; -} - -isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length, - const char *buf, const char *file, int line) -{ - trace_iov_t iov; - - iov.buf = buf; - iov.len = length; - return trace_write_packet_iov (ttype, 1, &iov, file, line); -} - -isc_result_t trace_write_packet_iov (trace_type_t *ttype, - int count, trace_iov_t *iov, - const char *file, int line) -{ - tracepacket_t tmp; - int status; - int i; - int length; - - /* Really shouldn't get called here, but it may be hard to turn off - tracing midstream if the trace file write fails or something. */ - if (tracing_stopped) - return 0; - - if (!ttype) { - log_error ("%s(%d): trace_write_packet with null trace type", - file ? file : "<unknown file>", line); - return ISC_R_INVALIDARG; - } - if (!traceoutfile) { - log_error ("%s(%d): trace_write_packet with no tracefile.", - file ? file : "<unknown file>", line); - return ISC_R_INVALIDARG; - } - - /* Compute the total length of the iov. */ - length = 0; - for (i = 0; i < count; i++) - length += iov [i].len; - - /* We have to swap out the data, because it may be read back on a - machine of different endianness. */ - tmp.type_index = htonl (ttype -> index); - tmp.when = htonl (time ((time_t *)0)); /* XXX */ - tmp.length = htonl (length); - - status = write (traceoutfile, &tmp, sizeof tmp); - if (status < 0) { - log_error ("%s(%d): trace_write_packet write failed: %m", - file, line); - return ISC_R_UNEXPECTED; - } else if (status != sizeof tmp) { - log_error ("%s(%d): trace_write_packet: short write (%d:%ld)", - file, line, status, (long)(sizeof tmp)); - trace_stop (); - } - - for (i = 0; i < count; i++) { - status = write (traceoutfile, iov [i].buf, iov [i].len); - if (status < 0) { - log_error ("%s(%d): %s write failed: %m", - file, line, "trace_write_packet"); - return ISC_R_UNEXPECTED; - } else if (status != iov [i].len) { - log_error ("%s(%d): %s: short write (%d:%d)", - file, line, - "trace_write_packet", status, length); - trace_stop (); - } - } - - /* Write padding on the end of the packet to align the next - packet to an 8-byte boundary. This is in case we decide to - use mmap in some clever way later on. */ - if (length % 8) { - static char zero [] = { 0, 0, 0, 0, 0, 0, 0 }; - unsigned padl = 8 - (length % 8); - - status = write (traceoutfile, zero, padl); - if (status < 0) { - log_error ("%s(%d): trace_write_packet write failed: %m", - file, line); - return ISC_R_UNEXPECTED; - } else if (status != padl) { - log_error ("%s(%d): trace_write_packet: short write (%d:%d)", - file, line, status, padl); - trace_stop (); - } - } - - return ISC_R_SUCCESS; -} - -void trace_type_stash (trace_type_t *tptr) -{ - trace_type_t **vec; - int delta; - if (trace_type_max <= tptr -> index) { - delta = tptr -> index - trace_type_max + 10; - vec = dmalloc (((trace_type_max + delta) * - sizeof (trace_type_t *)), MDL); - if (!vec) - return; - memset (&vec [trace_type_max], 0, - (sizeof (trace_type_t *)) * delta); - trace_type_max += delta; - if (trace_types) { - memcpy (vec, trace_types, - trace_type_count * sizeof (trace_type_t *)); - dfree (trace_types, MDL); - } - trace_types = vec; - } - trace_types [tptr -> index] = tptr; - if (tptr -> index >= trace_type_count) - trace_type_count = tptr -> index + 1; -} - -trace_type_t *trace_type_register (const char *name, - void *baggage, - void (*have_packet) (trace_type_t *, - unsigned, char *), - void (*stop_tracing) (trace_type_t *), - const char *file, int line) -{ - trace_type_t *ttmp, *tptr; - unsigned slen = strlen (name); - isc_result_t status; - - ttmp = dmalloc (sizeof *ttmp, file, line); - if (!ttmp) - return ttmp; - ttmp -> index = -1; - ttmp -> name = dmalloc (slen + 1, file, line); - if (!ttmp -> name) { - dfree (ttmp, file, line); - return (trace_type_t *)0; - } - strcpy (ttmp -> name, name); - ttmp -> have_packet = have_packet; - ttmp -> stop_tracing = stop_tracing; - - if (traceoutfile) { - status = trace_type_record (ttmp, slen, file, line); - if (status != ISC_R_SUCCESS) { - dfree (ttmp -> name, file, line); - dfree (ttmp, file, line); - return (trace_type_t *)0; - } - } else { - ttmp -> next = new_trace_types; - new_trace_types = ttmp; - } - - return ttmp; -} - -static isc_result_t trace_type_record (trace_type_t *ttmp, unsigned slen, - const char *file, int line) -{ - trace_index_mapping_t *tim; - isc_result_t status; - - tim = dmalloc (slen + TRACE_INDEX_MAPPING_SIZE, file, line); - if (!tim) - return ISC_R_NOMEMORY; - ttmp -> index = ++traceindex; - trace_type_stash (ttmp); - tim -> index = htonl (ttmp -> index); - memcpy (tim -> name, ttmp -> name, slen); - status = trace_write_packet (trace_types [0], - slen + TRACE_INDEX_MAPPING_SIZE, - (char *)tim, file, line); - dfree (tim, file, line); - return status; -} - -/* Stop all registered trace types from trying to trace. */ - -void trace_stop (void) -{ - int i; - - for (i = 0; i < trace_type_count; i++) - if (trace_types [i] -> stop_tracing) - (*(trace_types [i] -> stop_tracing)) - (trace_types [i]); - tracing_stopped = 1; -} - -void trace_index_map_input (trace_type_t *ttype, unsigned length, char *buf) -{ - trace_index_mapping_t *tmap; - unsigned len; - trace_type_t *tptr, **prev; - - if (length < TRACE_INDEX_MAPPING_SIZE) { - log_error ("short trace index mapping"); - return; - } - tmap = (trace_index_mapping_t *)buf; - - prev = &new_trace_types; - for (tptr = new_trace_types; tptr; tptr = tptr -> next) { - len = strlen (tptr -> name); - if (len == length - TRACE_INDEX_MAPPING_SIZE && - !memcmp (tptr -> name, tmap -> name, len)) { - tptr -> index = ntohl (tmap -> index); - trace_type_stash (tptr); - *prev = tptr -> next; - return; - } - prev = &tptr -> next; - } - - log_error ("No registered trace type for type name %.*s", - (int)length - TRACE_INDEX_MAPPING_SIZE, tmap -> name); - return; -} - -void trace_index_stop_tracing (trace_type_t *ttype) { } - -void trace_replay_init (void) -{ - trace_playback_flag = 1; -} - -void trace_file_replay (const char *filename) -{ - tracepacket_t *tpkt = (tracepacket_t *)0; - int status; - char *buf = (char *)0; - unsigned buflen; - unsigned bufmax = 0; - trace_type_t *ttype = (trace_type_t *)0; - isc_result_t result; - int len; - - traceinfile = fopen (filename, "r"); - if (!traceinfile) { - log_error ("Can't open tracefile %s: %m", filename); - return; - } -#if defined (HAVE_SETFD) - if (fcntl (fileno (traceinfile), F_SETFD, 1) < 0) - log_error ("Can't set close-on-exec on %s: %m", filename); -#endif - status = fread (&tracefile_header, 1, - sizeof tracefile_header, traceinfile); - if (status < sizeof tracefile_header) { - if (ferror (traceinfile)) - log_error ("Error reading trace file header: %m"); - else - log_error ("Short read on trace file header: %d %ld.", - status, (long)(sizeof tracefile_header)); - goto out; - } - tracefile_header.magic = ntohl (tracefile_header.magic); - tracefile_header.version = ntohl (tracefile_header.version); - tracefile_header.hlen = ntohl (tracefile_header.hlen); - tracefile_header.phlen = ntohl (tracefile_header.phlen); - - if (tracefile_header.magic != TRACEFILE_MAGIC) { - log_error ("%s: not a dhcp trace file.", filename); - goto out; - } - if (tracefile_header.version > TRACEFILE_VERSION) { - log_error ("tracefile version %ld > current %ld.", - (long int)tracefile_header.version, - (long int)TRACEFILE_VERSION); - goto out; - } - if (tracefile_header.phlen < sizeof *tpkt) { - log_error ("tracefile packet size too small - %ld < %ld", - (long int)tracefile_header.phlen, - (long int)sizeof *tpkt); - goto out; - } - len = (sizeof tracefile_header) - tracefile_header.hlen; - if (len < 0) { - log_error ("tracefile header size too small - %ld < %ld", - (long int)tracefile_header.hlen, - (long int)sizeof tracefile_header); - goto out; - } - if (len > 0) { - status = fseek (traceinfile, (long)len, SEEK_CUR); - if (status < 0) { - log_error ("can't seek past header: %m"); - goto out; - } - } - - tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL); - if (!tpkt) { - log_error ("can't allocate trace packet header."); - goto out; - } - - while ((result = trace_get_next_packet (&ttype, tpkt, &buf, &buflen, - &bufmax)) == ISC_R_SUCCESS) { - (*ttype -> have_packet) (ttype, tpkt -> length, buf); - ttype = (trace_type_t *)0; - } - out: - fclose (traceinfile); - if (buf) - dfree (buf, MDL); - if (tpkt) - dfree (tpkt, MDL); -} - -/* Get the next packet from the file. If ttp points to a nonzero pointer - to a trace type structure, check the next packet to see if it's of the - expected type, and back off if not. */ - -isc_result_t trace_get_next_packet (trace_type_t **ttp, - tracepacket_t *tpkt, - char **buf, unsigned *buflen, - unsigned *bufmax) -{ - trace_type_t *ttype; - unsigned paylen; - int status; - int len; - fpos_t curpos; - - status = fgetpos (traceinfile, &curpos); - if (status < 0) - log_error ("Can't save tracefile position: %m"); - - status = fread (tpkt, 1, (size_t)tracefile_header.phlen, traceinfile); - if (status < tracefile_header.phlen) { - if (ferror (traceinfile)) - log_error ("Error reading trace packet header: %m"); - else if (status == 0) - return ISC_R_EOF; - else - log_error ("Short read on trace packet header: " - "%ld %ld.", - (long int)status, - (long int)tracefile_header.phlen); - return ISC_R_PROTOCOLERROR; - } - - /* Swap the packet. */ - tpkt -> type_index = ntohl (tpkt -> type_index); - tpkt -> length = ntohl (tpkt -> length); - tpkt -> when = ntohl (tpkt -> when); - - /* See if there's a handler for this packet type. */ - if (tpkt -> type_index < trace_type_count && - trace_types [tpkt -> type_index]) - ttype = trace_types [tpkt -> type_index]; - else { - log_error ("Trace packet with unknown index %ld", - (long int)tpkt -> type_index); - return ISC_R_PROTOCOLERROR; - } - - /* If we were just hunting for the time marker, we've found it, - so back up to the beginning of the packet and return its - type. */ - if (ttp && *ttp == &trace_time_marker) { - *ttp = ttype; - status = fsetpos (traceinfile, &curpos); - if (status < 0) { - log_error ("fsetpos in tracefile failed: %m"); - return ISC_R_PROTOCOLERROR; - } - return ISC_R_EXISTS; - } - - /* If we were supposed to get a particular kind of packet, - check to see that we got the right kind. */ - if (ttp && *ttp && ttype != *ttp) { - log_error ("Read packet type %s when expecting %s", - ttype -> name, (*ttp) -> name); - status = fsetpos (traceinfile, &curpos); - if (status < 0) { - log_error ("fsetpos in tracefile failed: %m"); - return ISC_R_PROTOCOLERROR; - } - return ISC_R_UNEXPECTEDTOKEN; - } - - paylen = tpkt -> length; - if (paylen % 8) - paylen += 8 - (tpkt -> length % 8); - if (paylen > (*bufmax)) { - if ((*buf)) - dfree ((*buf), MDL); - (*bufmax) = ((paylen + 1023) & ~1023U); - (*buf) = dmalloc ((*bufmax), MDL); - if (!(*buf)) { - log_error ("Can't allocate input buffer sized %d", - (*bufmax)); - return ISC_R_NOMEMORY; - } - } - - status = fread ((*buf), 1, paylen, traceinfile); - if (status < paylen) { - if (ferror (traceinfile)) - log_error ("Error reading trace payload: %m"); - else - log_error ("Short read on trace payload: %d %d.", - status, paylen); - return ISC_R_PROTOCOLERROR; - } - - /* Store the actual length of the payload. */ - *buflen = tpkt -> length; - - if (trace_set_time_hook) - (*trace_set_time_hook) (tpkt -> when); - - if (ttp) - *ttp = ttype; - return ISC_R_SUCCESS; -} - -isc_result_t trace_get_packet (trace_type_t **ttp, - unsigned *buflen, char **buf) -{ - tracepacket_t *tpkt; - unsigned bufmax = 0; - isc_result_t status; - - if (!buf || *buf) - return ISC_R_INVALIDARG; - - tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL); - if (!tpkt) { - log_error ("can't allocate trace packet header."); - return ISC_R_NOMEMORY; - } - - status = trace_get_next_packet (ttp, tpkt, buf, buflen, &bufmax); - - dfree (tpkt, MDL); - return status; -} - -time_t trace_snoop_time (trace_type_t **ptp) -{ - tracepacket_t *tpkt; - unsigned bufmax = 0; - unsigned buflen = 0; - char *buf = (char *)0; - isc_result_t status; - time_t result; - trace_type_t *ttp; - - if (!ptp) - ptp = &ttp; - - tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL); - if (!tpkt) { - log_error ("can't allocate trace packet header."); - return ISC_R_NOMEMORY; - } - - *ptp = &trace_time_marker; - trace_get_next_packet (ptp, tpkt, &buf, &buflen, &bufmax); - result = tpkt -> when; - - dfree (tpkt, MDL); - return result; -} - -/* Get a packet from the trace input file that contains a file with the - specified name. We don't hunt for the packet - it should be the next - packet in the tracefile. If it's not, or something else bad happens, - return an error code. */ - -isc_result_t trace_get_file (trace_type_t *ttype, - const char *filename, unsigned *len, char **buf) -{ - fpos_t curpos; - unsigned max = 0; - tracepacket_t *tpkt; - int status; - isc_result_t result; - - /* Disallow some obvious bogosities. */ - if (!buf || !len || *buf) - return ISC_R_INVALIDARG; - - /* Save file position in case of filename mismatch. */ - status = fgetpos (traceinfile, &curpos); - if (status < 0) - log_error ("Can't save tracefile position: %m"); - - tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL); - if (!tpkt) { - log_error ("can't allocate trace packet header."); - return ISC_R_NOMEMORY; - } - - result = trace_get_next_packet (&ttype, tpkt, buf, len, &max); - if (result != ISC_R_SUCCESS) { - dfree (tpkt, MDL); - if (*buf) - dfree (*buf, MDL); - return result; - } - - /* Make sure the filename is right. */ - if (strcmp (filename, *buf)) { - log_error ("Read file %s when expecting %s", *buf, filename); - status = fsetpos (traceinfile, &curpos); - if (status < 0) { - log_error ("fsetpos in tracefile failed: %m"); - dfree (tpkt, MDL); - dfree (*buf, MDL); - return ISC_R_PROTOCOLERROR; - } - return ISC_R_UNEXPECTEDTOKEN; - } - - dfree (tpkt, MDL); - return ISC_R_SUCCESS; -} -#endif /* TRACING */ |