omapip/trace.c

Go to the documentation of this file.
00001 /* trace.c
00002 
00003    Subroutines that support tracing of OMAPI wire transactions and
00004    provide a mechanism for programs using OMAPI to trace their own
00005    transactions... */
00006 
00007 /*
00008  * Copyright (c) 2012,2014 by Internet Systems Consortium, Inc. ("ISC")
00009  * Copyright (c) 2009-2010 by Internet Systems Consortium, Inc. ("ISC")
00010  * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
00011  * Copyright (c) 2001-2003 by Internet Software Consortium
00012  *
00013  * Permission to use, copy, modify, and distribute this software for any
00014  * purpose with or without fee is hereby granted, provided that the above
00015  * copyright notice and this permission notice appear in all copies.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
00018  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00019  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
00020  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00021  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00022  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
00023  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00024  *
00025  *   Internet Systems Consortium, Inc.
00026  *   950 Charter Street
00027  *   Redwood City, CA 94063
00028  *   <info@isc.org>
00029  *   https://www.isc.org/
00030  *
00031  */
00032 
00033 #include "dhcpd.h"
00034 #include <omapip/omapip_p.h>
00035 #include <errno.h>
00036 
00037 #if defined (TRACING)
00038 void (*trace_set_time_hook) (TIME);
00039 static int tracing_stopped;
00040 static int traceoutfile;
00041 static int traceindex;
00042 static trace_type_t **trace_types;
00043 static int trace_type_count;
00044 static int trace_type_max;
00045 static trace_type_t *new_trace_types;
00046 static FILE *traceinfile;
00047 static tracefile_header_t tracefile_header;
00048 static int trace_playback_flag;
00049 trace_type_t trace_time_marker;
00050 
00051 #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
00052 extern omapi_array_t *trace_listeners;
00053 extern omapi_array_t *omapi_connections;
00054 
00055 extern int errno;
00056 
00057 void trace_free_all ()
00058 {
00059         trace_type_t *tp;
00060         int i;
00061         tp = new_trace_types;
00062         while (tp) {
00063                 new_trace_types = tp -> next;
00064                 if (tp -> name) {
00065                         dfree (tp -> name, MDL);
00066                         tp -> name = (char *)0;
00067                 }
00068                 dfree (tp, MDL);
00069                 tp = new_trace_types;
00070         }
00071         for (i = 0; i < trace_type_count; i++) {
00072                 if (trace_types [i]) {
00073                         if (trace_types [i] -> name)
00074                                 dfree (trace_types [i] -> name, MDL);
00075                         dfree (trace_types [i], MDL);
00076                 }
00077         }
00078         dfree (trace_types, MDL);
00079         trace_types = (trace_type_t **)0;
00080         trace_type_count = trace_type_max = 0;
00081 
00082         omapi_array_free (&trace_listeners, MDL);
00083         omapi_array_free (&omapi_connections, MDL);
00084 }
00085 #endif
00086 
00087 static isc_result_t trace_type_record (trace_type_t *,
00088                                        unsigned, const char *, int);
00089 
00090 int trace_playback ()
00091 {
00092         return trace_playback_flag;
00093 }
00094 
00095 int trace_record ()
00096 {
00097         if (traceoutfile && !tracing_stopped)
00098                 return 1;
00099         return 0;
00100 }
00101 
00102 isc_result_t trace_init (void (*set_time) (TIME),
00103                          const char *file, int line)
00104 {
00105         trace_type_t *root_type;
00106         static int root_setup = 0;
00107 
00108         if (root_setup)
00109                 return ISC_R_SUCCESS;
00110 
00111         trace_set_time_hook = set_time;
00112 
00113         root_type = trace_type_register ("trace-index-mapping",
00114                                          (void *)0, trace_index_map_input,
00115                                          trace_index_stop_tracing, file, line);
00116         if (!root_type)
00117                 return ISC_R_UNEXPECTED;
00118         if (new_trace_types == root_type)
00119                 new_trace_types = new_trace_types -> next;
00120         root_type -> index = 0;
00121         trace_type_stash (root_type);
00122 
00123         root_setup = 1;
00124         return ISC_R_SUCCESS;
00125 }
00126 
00127 isc_result_t trace_begin (const char *filename,
00128                           const char *file, int line)
00129 {
00130         tracefile_header_t tfh;
00131         int status;
00132         trace_type_t *tptr, *next;
00133         isc_result_t result;
00134 
00135         if (traceoutfile) {
00136                 log_error ("%s(%d): trace_begin called twice",
00137                            file, line);
00138                 return DHCP_R_INVALIDARG;
00139         }
00140 
00141         traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL | O_CLOEXEC, 0600);
00142         if (traceoutfile < 0 && errno == EEXIST) {
00143                 log_error ("WARNING: Overwriting trace file \"%s\"", filename);
00144                 traceoutfile = open (filename, O_WRONLY | O_EXCL | O_TRUNC | O_CLOEXEC,
00145                                      0600);
00146         }
00147 
00148         if (traceoutfile < 0) {
00149                 log_error ("%s(%d): trace_begin: %s: %m",
00150                            file, line, filename);
00151                 return ISC_R_UNEXPECTED;
00152         }
00153 #if defined (HAVE_SETFD)
00154         if (fcntl (traceoutfile, F_SETFD, 1) < 0)
00155                 log_error ("Can't set close-on-exec on %s: %m", filename);
00156 #endif
00157 
00158         tfh.magic = htonl (TRACEFILE_MAGIC);
00159         tfh.version = htonl (TRACEFILE_VERSION);
00160         tfh.hlen = htonl (sizeof (tracefile_header_t));
00161         tfh.phlen = htonl (sizeof (tracepacket_t));
00162         
00163         status = write (traceoutfile, &tfh, sizeof tfh);
00164         if (status < 0) {
00165                 log_error ("%s(%d): trace_begin write failed: %m", file, line);
00166                 return ISC_R_UNEXPECTED;
00167         } else if (status != sizeof tfh) {
00168                 log_error ("%s(%d): trace_begin: short write (%d:%ld)",
00169                            file, line, status, (long)(sizeof tfh));
00170                 trace_stop ();
00171                 return ISC_R_UNEXPECTED;
00172         }
00173 
00174         /* Stash all the types that have already been set up. */
00175         if (new_trace_types) {
00176                 next = new_trace_types;
00177                 new_trace_types = (trace_type_t *)0;
00178                 for (tptr = next; tptr; tptr = next) {
00179                         next = tptr -> next;
00180                         if (tptr -> index != 0) {
00181                                 result = (trace_type_record
00182                                           (tptr,
00183                                            strlen (tptr -> name), file, line));
00184                                 if (result != ISC_R_SUCCESS)
00185                                         return status;
00186                         }
00187                 }
00188         }
00189         
00190         return ISC_R_SUCCESS;
00191 }
00192 
00193 isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length,
00194                                  const char *buf, const char *file, int line)
00195 {
00196         trace_iov_t iov;
00197 
00198         iov.buf = buf;
00199         iov.len = length;
00200         return trace_write_packet_iov (ttype, 1, &iov, file, line);
00201 }
00202 
00203 isc_result_t trace_write_packet_iov (trace_type_t *ttype,
00204                                      int count, trace_iov_t *iov,
00205                                      const char *file, int line)
00206 {
00207         tracepacket_t tmp;
00208         int status;
00209         int i;
00210         int length;
00211 
00212         /* Really shouldn't get called here, but it may be hard to turn off
00213            tracing midstream if the trace file write fails or something. */
00214         if (tracing_stopped)
00215                 return 0;
00216 
00217         if (!ttype) {
00218                 log_error ("%s(%d): trace_write_packet with null trace type",
00219                            file ? file : "<unknown file>", line);
00220                 return DHCP_R_INVALIDARG;
00221         }
00222         if (!traceoutfile) {
00223                 log_error ("%s(%d): trace_write_packet with no tracefile.",
00224                            file ? file : "<unknown file>", line);
00225                 return DHCP_R_INVALIDARG;
00226         }
00227         
00228         /* Compute the total length of the iov. */
00229         length = 0;
00230         for (i = 0; i < count; i++)
00231                 length += iov [i].len;
00232 
00233         /* We have to swap out the data, because it may be read back on a
00234            machine of different endianness. */
00235         memset(&tmp, 0, sizeof(tmp));
00236         tmp.type_index = htonl (ttype -> index);
00237         tmp.when = htonl (time ((time_t *)0)); /* XXX */
00238         tmp.length = htonl (length);
00239 
00240         status = write (traceoutfile, &tmp, sizeof tmp);
00241         if (status < 0) {
00242                 log_error ("%s(%d): trace_write_packet write failed: %m",
00243                            file, line);
00244                 return ISC_R_UNEXPECTED;
00245         } else if (status != sizeof tmp) {
00246                 log_error ("%s(%d): trace_write_packet: short write (%d:%ld)",
00247                            file, line, status, (long)(sizeof tmp));
00248                 trace_stop ();
00249         }
00250 
00251         for (i = 0; i < count; i++) {
00252                 status = write (traceoutfile, iov [i].buf, iov [i].len);
00253                 if (status < 0) {
00254                         log_error ("%s(%d): %s write failed: %m",
00255                                    file, line, "trace_write_packet");
00256                         return ISC_R_UNEXPECTED;
00257                 } else if (status != iov [i].len) {
00258                         log_error ("%s(%d): %s: short write (%d:%d)",
00259                                    file, line,
00260                                    "trace_write_packet", status, length);
00261                         trace_stop ();
00262                 }
00263         }
00264 
00265         /* Write padding on the end of the packet to align the next
00266            packet to an 8-byte boundary.   This is in case we decide to
00267            use mmap in some clever way later on. */
00268         if (length % 8) {
00269             static char zero [] = { 0, 0, 0, 0, 0, 0, 0 };
00270             unsigned padl = 8 - (length % 8);
00271                 
00272             status = write (traceoutfile, zero, padl);
00273             if (status < 0) {
00274                 log_error ("%s(%d): trace_write_packet write failed: %m",
00275                            file, line);
00276                 return ISC_R_UNEXPECTED;
00277             } else if (status != padl) {
00278                 log_error ("%s(%d): trace_write_packet: short write (%d:%d)",
00279                            file, line, status, padl);
00280                 trace_stop ();
00281             }
00282         }
00283 
00284         return ISC_R_SUCCESS;
00285 }
00286 
00287 void trace_type_stash (trace_type_t *tptr)
00288 {
00289         trace_type_t **vec;
00290         int delta;
00291         if (trace_type_max <= tptr -> index) {
00292                 delta = tptr -> index - trace_type_max + 10;
00293                 vec = dmalloc (((trace_type_max + delta) *
00294                                 sizeof (trace_type_t *)), MDL);
00295                 if (!vec)
00296                         return;
00297                 memset (&vec [trace_type_max], 0,
00298                         (sizeof (trace_type_t *)) * delta);
00299                 trace_type_max += delta;
00300                 if (trace_types) {
00301                     memcpy (vec, trace_types,
00302                             trace_type_count * sizeof (trace_type_t *));
00303                     dfree (trace_types, MDL);
00304                 }
00305                 trace_types = vec;
00306         }
00307         trace_types [tptr -> index] = tptr;
00308         if (tptr -> index >= trace_type_count)
00309                 trace_type_count = tptr -> index + 1;
00310 }
00311 
00312 trace_type_t *trace_type_register (const char *name,
00313                                    void *baggage,
00314                                    void (*have_packet) (trace_type_t *,
00315                                                         unsigned, char *),
00316                                    void (*stop_tracing) (trace_type_t *),
00317                                    const char *file, int line)
00318 {
00319         trace_type_t *ttmp;
00320         unsigned slen = strlen (name);
00321         isc_result_t status;
00322 
00323         ttmp = dmalloc (sizeof *ttmp, file, line);
00324         if (!ttmp)
00325                 return ttmp;
00326         ttmp -> index = -1;
00327         ttmp -> name = dmalloc (slen + 1, file, line);
00328         if (!ttmp -> name) {
00329                 dfree (ttmp, file, line);
00330                 return (trace_type_t *)0;
00331         }
00332         strcpy (ttmp -> name, name);
00333         ttmp -> have_packet = have_packet;
00334         ttmp -> stop_tracing = stop_tracing;
00335         
00336         if (traceoutfile) {
00337                 status = trace_type_record (ttmp, slen, file, line);
00338                 if (status != ISC_R_SUCCESS) {
00339                         dfree (ttmp -> name, file, line);
00340                         dfree (ttmp, file, line);
00341                         return (trace_type_t *)0;
00342                 }
00343         } else {
00344                 ttmp -> next = new_trace_types;
00345                 new_trace_types = ttmp;
00346         }
00347 
00348         return ttmp;
00349 }
00350                                                    
00351 static isc_result_t trace_type_record (trace_type_t *ttmp, unsigned slen,
00352                                        const char *file, int line)
00353 {
00354         trace_index_mapping_t *tim;
00355         isc_result_t status;
00356 
00357         tim = dmalloc (slen + TRACE_INDEX_MAPPING_SIZE, file, line);
00358         if (!tim)
00359                 return ISC_R_NOMEMORY;
00360         ttmp -> index = ++traceindex;
00361         trace_type_stash (ttmp);
00362         tim -> index = htonl (ttmp -> index);
00363         memcpy (tim -> name, ttmp -> name, slen);
00364         status = trace_write_packet (trace_types [0],
00365                                      slen + TRACE_INDEX_MAPPING_SIZE,
00366                                      (char *)tim, file, line);
00367         dfree (tim, file, line);
00368         return status;
00369 }
00370 
00371 /* Stop all registered trace types from trying to trace. */
00372 
00373 void trace_stop (void)
00374 {
00375         int i;
00376 
00377         for (i = 0; i < trace_type_count; i++)
00378                 if (trace_types [i] -> stop_tracing)
00379                         (*(trace_types [i] -> stop_tracing))
00380                                 (trace_types [i]);
00381         tracing_stopped = 1;
00382 }
00383 
00384 void trace_index_map_input (trace_type_t *ttype, unsigned length, char *buf)
00385 {
00386         trace_index_mapping_t *tmap;
00387         unsigned len;
00388         trace_type_t *tptr, **prev;
00389 
00390         if (length < TRACE_INDEX_MAPPING_SIZE) {
00391                 log_error ("short trace index mapping");
00392                 return;
00393         }
00394         tmap = (trace_index_mapping_t *)buf;
00395 
00396         prev = &new_trace_types;
00397         for (tptr = new_trace_types; tptr; tptr = tptr -> next) {
00398                 len = strlen (tptr -> name);
00399                 if (len == length - TRACE_INDEX_MAPPING_SIZE &&
00400                     !memcmp (tptr -> name, tmap -> name, len)) {
00401                         tptr -> index = ntohl (tmap -> index);
00402                         trace_type_stash (tptr);
00403                         *prev = tptr -> next;
00404                         return;
00405                 }
00406                 prev = &tptr -> next;
00407         }
00408         
00409         log_error ("No registered trace type for type name %.*s",
00410                    (int)length - TRACE_INDEX_MAPPING_SIZE, tmap -> name);
00411         return;
00412 }
00413 
00414 void trace_index_stop_tracing (trace_type_t *ttype) { }
00415 
00416 void trace_replay_init (void)
00417 {
00418         trace_playback_flag = 1;
00419 }
00420 
00421 void trace_file_replay (const char *filename)
00422 {
00423         tracepacket_t *tpkt = NULL;
00424         int status;
00425         char *buf = NULL;
00426         unsigned buflen;
00427         unsigned bufmax = 0;
00428         trace_type_t *ttype = NULL;
00429         isc_result_t result;
00430         int len;
00431 
00432         traceinfile = fopen (filename, "re");
00433         if (!traceinfile) {
00434                 log_error("Can't open tracefile %s: %m", filename);
00435                 return;
00436         }
00437 #if defined (HAVE_SETFD)
00438         if (fcntl (fileno(traceinfile), F_SETFD, 1) < 0)
00439                 log_error("Can't set close-on-exec on %s: %m", filename);
00440 #endif
00441         status = fread(&tracefile_header, 1,
00442                        sizeof tracefile_header, traceinfile);
00443         if (status < sizeof tracefile_header) {
00444                 if (ferror(traceinfile))
00445                         log_error("Error reading trace file header: %m");
00446                 else
00447                         log_error("Short read on trace file header: %d %ld.",
00448                                   status, (long)(sizeof tracefile_header));
00449                 goto out;
00450         }
00451         tracefile_header.magic = ntohl(tracefile_header.magic);
00452         tracefile_header.version = ntohl(tracefile_header.version);
00453         tracefile_header.hlen = ntohl(tracefile_header.hlen);
00454         tracefile_header.phlen = ntohl(tracefile_header.phlen);
00455 
00456         if (tracefile_header.magic != TRACEFILE_MAGIC) {
00457                 log_error("%s: not a dhcp trace file.", filename);
00458                 goto out;
00459         }
00460         if (tracefile_header.version > TRACEFILE_VERSION) {
00461                 log_error ("tracefile version %ld > current %ld.",
00462                            (long int)tracefile_header.version,
00463                            (long int)TRACEFILE_VERSION);
00464                 goto out;
00465         }
00466         if (tracefile_header.phlen < sizeof *tpkt) {
00467                 log_error("tracefile packet size too small - %ld < %ld",
00468                           (long int)tracefile_header.phlen,
00469                           (long int)sizeof *tpkt);
00470                 goto out;
00471         }
00472         len = (sizeof tracefile_header) - tracefile_header.hlen;
00473         if (len < 0) {
00474                 log_error("tracefile header size too small - %ld < %ld",
00475                           (long int)tracefile_header.hlen,
00476                           (long int)sizeof tracefile_header);
00477                 goto out;
00478         }
00479         if (len > 0) {
00480                 status = fseek(traceinfile, (long)len, SEEK_CUR);
00481                 if (status < 0) {
00482                         log_error("can't seek past header: %m");
00483                         goto out;
00484                 }
00485         }
00486 
00487         tpkt = dmalloc((unsigned)tracefile_header.phlen, MDL);
00488         if (tpkt == NULL) {
00489                 log_error ("can't allocate trace packet header.");
00490                 goto out;
00491         }
00492 
00493         while ((result = trace_get_next_packet(&ttype, tpkt, &buf, &buflen,
00494                                                &bufmax)) == ISC_R_SUCCESS) {
00495             (*ttype->have_packet)(ttype, tpkt->length, buf);
00496             ttype = NULL;
00497         }
00498       out:
00499         fclose(traceinfile);
00500         if (buf != NULL)
00501                 dfree(buf, MDL);
00502         if (tpkt != NULL)
00503                 dfree(tpkt, MDL);
00504 }
00505 
00506 /* Get the next packet from the file.   If ttp points to a nonzero pointer
00507    to a trace type structure, check the next packet to see if it's of the
00508    expected type, and back off if not. */
00509 
00510 isc_result_t trace_get_next_packet (trace_type_t **ttp,
00511                                     tracepacket_t *tpkt,
00512                                     char **buf, unsigned *buflen,
00513                                     unsigned *bufmax)
00514 {
00515         trace_type_t *ttype;
00516         unsigned paylen;
00517         int status, curposok = 0;
00518         fpos_t curpos;
00519 
00520         while(1) {
00521                 curposok = 0;
00522                 status = fgetpos(traceinfile, &curpos);
00523                 if (status < 0) {
00524                         log_error("Can't save tracefile position: %m");
00525                 } else {
00526                         curposok = 1;
00527                 }
00528 
00529                 status = fread(tpkt, 1, (size_t)tracefile_header.phlen,
00530                                traceinfile);
00531                 if (status < tracefile_header.phlen) {
00532                         if (ferror(traceinfile))
00533                                 log_error("Error reading trace packet header: "
00534                                           "%m");
00535                         else if (status == 0)
00536                                 return ISC_R_EOF;
00537                         else
00538                                 log_error ("Short read on trace packet header:"
00539                                            " %ld %ld.",
00540                                            (long int)status,
00541                                            (long int)tracefile_header.phlen);
00542                         return DHCP_R_PROTOCOLERROR;
00543                 }
00544 
00545                 /* Swap the packet. */
00546                 tpkt->type_index = ntohl(tpkt -> type_index);
00547                 tpkt->length = ntohl(tpkt -> length);
00548                 tpkt->when = ntohl(tpkt -> when);
00549         
00550                 /* See if there's a handler for this packet type. */
00551                 if (tpkt->type_index < trace_type_count &&
00552                     trace_types[tpkt->type_index])
00553                         ttype = trace_types[tpkt->type_index];
00554                 else {
00555                         log_error ("Trace packet with unknown index %ld",
00556                                    (long int)tpkt->type_index);
00557                         return DHCP_R_PROTOCOLERROR;
00558                 }
00559 
00560                 /*
00561                  * Determine if we should try to expire any timer events.
00562                  * We do so if:
00563                  *   we aren't looking for a specific type of packet
00564                  *   we have a hook to use to update the timer
00565                  *   the timestamp on the packet doesn't match the current time
00566                  * When we do so we rewind the file to the beginning of this
00567                  * packet and then try for a new packet.  This allows
00568                  * any code triggered by a timeout to get the current packet
00569                  * while we get the next one.
00570                  */
00571 
00572                 if ((ttp != NULL) && (*ttp == NULL) &&
00573                     (tpkt->when != cur_tv.tv_sec) &&
00574                     (trace_set_time_hook != NULL)) {
00575                         if (curposok == 0) {
00576                                 log_error("no curpos for fsetpos in "
00577                                           "tracefile");
00578                                 return DHCP_R_PROTOCOLERROR;
00579                         }
00580                                 
00581                         status = fsetpos(traceinfile, &curpos);
00582                         if (status < 0) {
00583                                 log_error("fsetpos in tracefile failed: %m");
00584                                 return DHCP_R_PROTOCOLERROR;
00585                         }
00586 
00587                         (*trace_set_time_hook) (tpkt->when);
00588                         continue;
00589                 }
00590                 break;
00591         }
00592 
00593         /* If we were supposed to get a particular kind of packet,
00594            check to see that we got the right kind. */
00595         if (ttp && *ttp && ttype != *ttp) {
00596                 log_error ("Read packet type %s when expecting %s",
00597                            ttype -> name, (*ttp) -> name);
00598                 status = fsetpos (traceinfile, &curpos);
00599                 if (status < 0) {
00600                         log_error ("fsetpos in tracefile failed: %m");
00601                         return DHCP_R_PROTOCOLERROR;
00602                 }
00603                 return ISC_R_UNEXPECTEDTOKEN;
00604         }
00605 
00606         paylen = tpkt -> length;
00607         if (paylen % 8)
00608                 paylen += 8 - (tpkt -> length % 8);
00609         if (paylen > (*bufmax)) {
00610                 if ((*buf))
00611                         dfree ((*buf), MDL);
00612                 (*bufmax) = ((paylen + 1023) & ~1023U);
00613                 (*buf) = dmalloc ((*bufmax), MDL);
00614                 if (!(*buf)) {
00615                         log_error ("Can't allocate input buffer sized %d",
00616                                    (*bufmax));
00617                         return ISC_R_NOMEMORY;
00618                 }
00619         }
00620         
00621         status = fread ((*buf), 1, paylen, traceinfile);
00622         if (status < paylen) {
00623                 if (ferror (traceinfile))
00624                         log_error ("Error reading trace payload: %m");
00625                 else
00626                         log_error ("Short read on trace payload: %d %d.",
00627                                    status, paylen);
00628                 return DHCP_R_PROTOCOLERROR;
00629         }
00630 
00631         /* Store the actual length of the payload. */
00632         *buflen = tpkt -> length;
00633 
00634         if (ttp)
00635                 *ttp = ttype;
00636         return ISC_R_SUCCESS;
00637 }
00638 
00639 isc_result_t trace_get_packet (trace_type_t **ttp,
00640                                unsigned *buflen, char **buf)
00641 {
00642         tracepacket_t *tpkt;
00643         unsigned bufmax = 0;
00644         isc_result_t status;
00645 
00646         if (!buf || *buf)
00647                 return DHCP_R_INVALIDARG;
00648 
00649         tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
00650         if (!tpkt) {
00651                 log_error ("can't allocate trace packet header.");
00652                 return ISC_R_NOMEMORY;
00653         }
00654 
00655         status = trace_get_next_packet (ttp, tpkt, buf, buflen, &bufmax);
00656 
00657         dfree (tpkt, MDL);
00658         return status;
00659 }
00660 
00661 /* Get a packet from the trace input file that contains a file with the
00662    specified name.   We don't hunt for the packet - it should be the next
00663    packet in the tracefile.   If it's not, or something else bad happens,
00664    return an error code. */
00665 
00666 isc_result_t trace_get_file (trace_type_t *ttype,
00667                              const char *filename, unsigned *len, char **buf)
00668 {
00669         fpos_t curpos;
00670         unsigned max = 0;
00671         tracepacket_t *tpkt;
00672         int status;
00673         isc_result_t result;
00674 
00675         /* Disallow some obvious bogosities. */
00676         if (!buf || !len || *buf)
00677                 return DHCP_R_INVALIDARG;
00678 
00679         /* Save file position in case of filename mismatch. */
00680         status = fgetpos (traceinfile, &curpos);
00681         if (status < 0)
00682                 log_error ("Can't save tracefile position: %m");
00683 
00684         tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
00685         if (!tpkt) {
00686                 log_error ("can't allocate trace packet header.");
00687                 return ISC_R_NOMEMORY;
00688         }
00689 
00690         result = trace_get_next_packet (&ttype, tpkt, buf, len, &max);
00691         /* done with tpkt, free it */
00692         dfree (tpkt, MDL);
00693         if (result != ISC_R_SUCCESS) {
00694                 if (*buf) {
00695                         dfree (*buf, MDL);
00696                         *buf = NULL;
00697                 }
00698                 return result;
00699         }
00700 
00701         /* Make sure the filename is right. */
00702         if (strcmp (filename, *buf)) {
00703                 log_error ("Read file %s when expecting %s", *buf, filename);
00704                 dfree (*buf, MDL);
00705                 *buf = NULL;
00706 
00707                 status = fsetpos (traceinfile, &curpos);
00708                 if (status < 0) {
00709                         log_error ("fsetpos in tracefile failed: %m");
00710                         return DHCP_R_PROTOCOLERROR;
00711                 }
00712                 return ISC_R_UNEXPECTEDTOKEN;
00713         }
00714 
00715         return ISC_R_SUCCESS;
00716 }
00717 #endif /* TRACING */

Generated on 5 Apr 2014 for ISC DHCP by  doxygen 1.6.1