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>