Annotation of embedaddon/dhcp/omapip/trace.c, revision 1.1.1.1

1.1       misho       1: /* trace.c
                      2: 
                      3:    Subroutines that support tracing of OMAPI wire transactions and
                      4:    provide a mechanism for programs using OMAPI to trace their own
                      5:    transactions... */
                      6: 
                      7: /*
                      8:  * Copyright (c) 2004-2007,2009 by Internet Systems Consortium, Inc. ("ISC")
                      9:  * Copyright (c) 2001-2003 by Internet Software Consortium
                     10:  *
                     11:  * Permission to use, copy, modify, and distribute this software for any
                     12:  * purpose with or without fee is hereby granted, provided that the above
                     13:  * copyright notice and this permission notice appear in all copies.
                     14:  *
                     15:  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
                     16:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
                     18:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     19:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     20:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
                     21:  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     22:  *
                     23:  *   Internet Systems Consortium, Inc.
                     24:  *   950 Charter Street
                     25:  *   Redwood City, CA 94063
                     26:  *   <info@isc.org>
                     27:  *   https://www.isc.org/
                     28:  *
                     29:  * This software has been written for Internet Systems Consortium
                     30:  * by Ted Lemon, as part of a project for Nominum, Inc.   To learn more
                     31:  * about Internet Systems Consortium, see https://www.isc.org/.  To
                     32:  * learn more about Nominum, Inc., see ``http://www.nominum.com''.
                     33:  */
                     34: 
                     35: #include "dhcpd.h"
                     36: #include <omapip/omapip_p.h>
                     37: #include <errno.h>
                     38: 
                     39: #if defined (TRACING)
                     40: void (*trace_set_time_hook) (TIME);
                     41: static int tracing_stopped;
                     42: static int traceoutfile;
                     43: static int traceindex;
                     44: static trace_type_t **trace_types;
                     45: static int trace_type_count;
                     46: static int trace_type_max;
                     47: static trace_type_t *new_trace_types;
                     48: static FILE *traceinfile;
                     49: static tracefile_header_t tracefile_header;
                     50: static int trace_playback_flag;
                     51: trace_type_t trace_time_marker;
                     52: 
                     53: #if defined (DEBUG_MEMORY_LEAKAGE) || defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
                     54: extern omapi_array_t *trace_listeners;
                     55: extern omapi_array_t *omapi_connections;
                     56: 
                     57: extern int errno;
                     58: 
                     59: void trace_free_all ()
                     60: {
                     61:        trace_type_t *tp;
                     62:        int i;
                     63:        tp = new_trace_types;
                     64:        while (tp) {
                     65:                new_trace_types = tp -> next;
                     66:                if (tp -> name) {
                     67:                        dfree (tp -> name, MDL);
                     68:                        tp -> name = (char *)0;
                     69:                }
                     70:                dfree (tp, MDL);
                     71:                tp = new_trace_types;
                     72:        }
                     73:        for (i = 0; i < trace_type_count; i++) {
                     74:                if (trace_types [i]) {
                     75:                        if (trace_types [i] -> name)
                     76:                                dfree (trace_types [i] -> name, MDL);
                     77:                        dfree (trace_types [i], MDL);
                     78:                }
                     79:        }
                     80:        dfree (trace_types, MDL);
                     81:        trace_types = (trace_type_t **)0;
                     82:        trace_type_count = trace_type_max = 0;
                     83: 
                     84:        omapi_array_free (&trace_listeners, MDL);
                     85:        omapi_array_free (&omapi_connections, MDL);
                     86: }
                     87: #endif
                     88: 
                     89: static isc_result_t trace_type_record (trace_type_t *,
                     90:                                       unsigned, const char *, int);
                     91: 
                     92: int trace_playback ()
                     93: {
                     94:        return trace_playback_flag;
                     95: }
                     96: 
                     97: int trace_record ()
                     98: {
                     99:        if (traceoutfile && !tracing_stopped)
                    100:                return 1;
                    101:        return 0;
                    102: }
                    103: 
                    104: isc_result_t trace_init (void (*set_time) (TIME),
                    105:                         const char *file, int line)
                    106: {
                    107:        trace_type_t *root_type;
                    108:        static int root_setup = 0;
                    109: 
                    110:        if (root_setup)
                    111:                return ISC_R_SUCCESS;
                    112: 
                    113:        trace_set_time_hook = set_time;
                    114: 
                    115:        root_type = trace_type_register ("trace-index-mapping",
                    116:                                         (void *)0, trace_index_map_input,
                    117:                                         trace_index_stop_tracing, file, line);
                    118:        if (!root_type)
                    119:                return ISC_R_UNEXPECTED;
                    120:        if (new_trace_types == root_type)
                    121:                new_trace_types = new_trace_types -> next;
                    122:        root_type -> index = 0;
                    123:        trace_type_stash (root_type);
                    124: 
                    125:        root_setup = 1;
                    126:        return ISC_R_SUCCESS;
                    127: }
                    128: 
                    129: isc_result_t trace_begin (const char *filename,
                    130:                          const char *file, int line)
                    131: {
                    132:        tracefile_header_t tfh;
                    133:        int status;
                    134:        trace_type_t *tptr, *next;
                    135:        isc_result_t result;
                    136: 
                    137:        if (traceoutfile) {
                    138:                log_error ("%s(%d): trace_begin called twice",
                    139:                           file, line);
                    140:                return ISC_R_INVALIDARG;
                    141:        }
                    142: 
                    143:        traceoutfile = open (filename, O_CREAT | O_WRONLY | O_EXCL, 0600);
                    144:        if (traceoutfile < 0 && errno == EEXIST) {
                    145:                log_error ("WARNING: Overwriting trace file \"%s\"", filename);
                    146:                traceoutfile = open (filename, O_WRONLY | O_EXCL, 0600);
                    147:        }
                    148: 
                    149:        if (traceoutfile < 0) {
                    150:                log_error ("%s(%d): trace_begin: %s: %m",
                    151:                           file, line, filename);
                    152:                return ISC_R_UNEXPECTED;
                    153:        }
                    154: #if defined (HAVE_SETFD)
                    155:        if (fcntl (traceoutfile, F_SETFD, 1) < 0)
                    156:                log_error ("Can't set close-on-exec on %s: %m", filename);
                    157: #endif
                    158: 
                    159:        tfh.magic = htonl (TRACEFILE_MAGIC);
                    160:        tfh.version = htonl (TRACEFILE_VERSION);
                    161:        tfh.hlen = htonl (sizeof (tracefile_header_t));
                    162:        tfh.phlen = htonl (sizeof (tracepacket_t));
                    163:        
                    164:        status = write (traceoutfile, &tfh, sizeof tfh);
                    165:        if (status < 0) {
                    166:                log_error ("%s(%d): trace_begin write failed: %m", file, line);
                    167:                return ISC_R_UNEXPECTED;
                    168:        } else if (status != sizeof tfh) {
                    169:                log_error ("%s(%d): trace_begin: short write (%d:%ld)",
                    170:                           file, line, status, (long)(sizeof tfh));
                    171:                trace_stop ();
                    172:                return ISC_R_UNEXPECTED;
                    173:        }
                    174: 
                    175:        /* Stash all the types that have already been set up. */
                    176:        if (new_trace_types) {
                    177:                next = new_trace_types;
                    178:                new_trace_types = (trace_type_t *)0;
                    179:                for (tptr = next; tptr; tptr = next) {
                    180:                        next = tptr -> next;
                    181:                        if (tptr -> index != 0) {
                    182:                                result = (trace_type_record
                    183:                                          (tptr,
                    184:                                           strlen (tptr -> name), file, line));
                    185:                                if (result != ISC_R_SUCCESS)
                    186:                                        return status;
                    187:                        }
                    188:                }
                    189:        }
                    190:        
                    191:        return ISC_R_SUCCESS;
                    192: }
                    193: 
                    194: isc_result_t trace_write_packet (trace_type_t *ttype, unsigned length,
                    195:                                 const char *buf, const char *file, int line)
                    196: {
                    197:        trace_iov_t iov;
                    198: 
                    199:        iov.buf = buf;
                    200:        iov.len = length;
                    201:        return trace_write_packet_iov (ttype, 1, &iov, file, line);
                    202: }
                    203: 
                    204: isc_result_t trace_write_packet_iov (trace_type_t *ttype,
                    205:                                     int count, trace_iov_t *iov,
                    206:                                     const char *file, int line)
                    207: {
                    208:        tracepacket_t tmp;
                    209:        int status;
                    210:        int i;
                    211:        int length;
                    212: 
                    213:        /* Really shouldn't get called here, but it may be hard to turn off
                    214:           tracing midstream if the trace file write fails or something. */
                    215:        if (tracing_stopped)
                    216:                return 0;
                    217: 
                    218:        if (!ttype) {
                    219:                log_error ("%s(%d): trace_write_packet with null trace type",
                    220:                           file ? file : "<unknown file>", line);
                    221:                return ISC_R_INVALIDARG;
                    222:        }
                    223:        if (!traceoutfile) {
                    224:                log_error ("%s(%d): trace_write_packet with no tracefile.",
                    225:                           file ? file : "<unknown file>", line);
                    226:                return ISC_R_INVALIDARG;
                    227:        }
                    228:        
                    229:        /* Compute the total length of the iov. */
                    230:        length = 0;
                    231:        for (i = 0; i < count; i++)
                    232:                length += iov [i].len;
                    233: 
                    234:        /* We have to swap out the data, because it may be read back on a
                    235:           machine of different endianness. */
                    236:        tmp.type_index = htonl (ttype -> index);
                    237:        tmp.when = htonl (time ((time_t *)0)); /* XXX */
                    238:        tmp.length = htonl (length);
                    239: 
                    240:        status = write (traceoutfile, &tmp, sizeof tmp);
                    241:        if (status < 0) {
                    242:                log_error ("%s(%d): trace_write_packet write failed: %m",
                    243:                           file, line);
                    244:                return ISC_R_UNEXPECTED;
                    245:        } else if (status != sizeof tmp) {
                    246:                log_error ("%s(%d): trace_write_packet: short write (%d:%ld)",
                    247:                           file, line, status, (long)(sizeof tmp));
                    248:                trace_stop ();
                    249:        }
                    250: 
                    251:        for (i = 0; i < count; i++) {
                    252:                status = write (traceoutfile, iov [i].buf, iov [i].len);
                    253:                if (status < 0) {
                    254:                        log_error ("%s(%d): %s write failed: %m",
                    255:                                   file, line, "trace_write_packet");
                    256:                        return ISC_R_UNEXPECTED;
                    257:                } else if (status != iov [i].len) {
                    258:                        log_error ("%s(%d): %s: short write (%d:%d)",
                    259:                                   file, line,
                    260:                                   "trace_write_packet", status, length);
                    261:                        trace_stop ();
                    262:                }
                    263:        }
                    264: 
                    265:        /* Write padding on the end of the packet to align the next
                    266:           packet to an 8-byte boundary.   This is in case we decide to
                    267:           use mmap in some clever way later on. */
                    268:        if (length % 8) {
                    269:            static char zero [] = { 0, 0, 0, 0, 0, 0, 0 };
                    270:            unsigned padl = 8 - (length % 8);
                    271:                
                    272:            status = write (traceoutfile, zero, padl);
                    273:            if (status < 0) {
                    274:                log_error ("%s(%d): trace_write_packet write failed: %m",
                    275:                           file, line);
                    276:                return ISC_R_UNEXPECTED;
                    277:            } else if (status != padl) {
                    278:                log_error ("%s(%d): trace_write_packet: short write (%d:%d)",
                    279:                           file, line, status, padl);
                    280:                trace_stop ();
                    281:            }
                    282:        }
                    283: 
                    284:        return ISC_R_SUCCESS;
                    285: }
                    286: 
                    287: void trace_type_stash (trace_type_t *tptr)
                    288: {
                    289:        trace_type_t **vec;
                    290:        int delta;
                    291:        if (trace_type_max <= tptr -> index) {
                    292:                delta = tptr -> index - trace_type_max + 10;
                    293:                vec = dmalloc (((trace_type_max + delta) *
                    294:                                sizeof (trace_type_t *)), MDL);
                    295:                if (!vec)
                    296:                        return;
                    297:                memset (&vec [trace_type_max], 0,
                    298:                        (sizeof (trace_type_t *)) * delta);
                    299:                trace_type_max += delta;
                    300:                if (trace_types) {
                    301:                    memcpy (vec, trace_types,
                    302:                            trace_type_count * sizeof (trace_type_t *));
                    303:                    dfree (trace_types, MDL);
                    304:                }
                    305:                trace_types = vec;
                    306:        }
                    307:        trace_types [tptr -> index] = tptr;
                    308:        if (tptr -> index >= trace_type_count)
                    309:                trace_type_count = tptr -> index + 1;
                    310: }
                    311: 
                    312: trace_type_t *trace_type_register (const char *name,
                    313:                                   void *baggage,
                    314:                                   void (*have_packet) (trace_type_t *,
                    315:                                                        unsigned, char *),
                    316:                                   void (*stop_tracing) (trace_type_t *),
                    317:                                   const char *file, int line)
                    318: {
                    319:        trace_type_t *ttmp;
                    320:        unsigned slen = strlen (name);
                    321:        isc_result_t status;
                    322: 
                    323:        ttmp = dmalloc (sizeof *ttmp, file, line);
                    324:        if (!ttmp)
                    325:                return ttmp;
                    326:        ttmp -> index = -1;
                    327:        ttmp -> name = dmalloc (slen + 1, file, line);
                    328:        if (!ttmp -> name) {
                    329:                dfree (ttmp, file, line);
                    330:                return (trace_type_t *)0;
                    331:        }
                    332:        strcpy (ttmp -> name, name);
                    333:        ttmp -> have_packet = have_packet;
                    334:        ttmp -> stop_tracing = stop_tracing;
                    335:        
                    336:        if (traceoutfile) {
                    337:                status = trace_type_record (ttmp, slen, file, line);
                    338:                if (status != ISC_R_SUCCESS) {
                    339:                        dfree (ttmp -> name, file, line);
                    340:                        dfree (ttmp, file, line);
                    341:                        return (trace_type_t *)0;
                    342:                }
                    343:        } else {
                    344:                ttmp -> next = new_trace_types;
                    345:                new_trace_types = ttmp;
                    346:        }
                    347: 
                    348:        return ttmp;
                    349: }
                    350:                                                   
                    351: static isc_result_t trace_type_record (trace_type_t *ttmp, unsigned slen,
                    352:                                       const char *file, int line)
                    353: {
                    354:        trace_index_mapping_t *tim;
                    355:        isc_result_t status;
                    356: 
                    357:        tim = dmalloc (slen + TRACE_INDEX_MAPPING_SIZE, file, line);
                    358:        if (!tim)
                    359:                return ISC_R_NOMEMORY;
                    360:        ttmp -> index = ++traceindex;
                    361:        trace_type_stash (ttmp);
                    362:        tim -> index = htonl (ttmp -> index);
                    363:        memcpy (tim -> name, ttmp -> name, slen);
                    364:        status = trace_write_packet (trace_types [0],
                    365:                                     slen + TRACE_INDEX_MAPPING_SIZE,
                    366:                                     (char *)tim, file, line);
                    367:        dfree (tim, file, line);
                    368:        return status;
                    369: }
                    370: 
                    371: /* Stop all registered trace types from trying to trace. */
                    372: 
                    373: void trace_stop (void)
                    374: {
                    375:        int i;
                    376: 
                    377:        for (i = 0; i < trace_type_count; i++)
                    378:                if (trace_types [i] -> stop_tracing)
                    379:                        (*(trace_types [i] -> stop_tracing))
                    380:                                (trace_types [i]);
                    381:        tracing_stopped = 1;
                    382: }
                    383: 
                    384: void trace_index_map_input (trace_type_t *ttype, unsigned length, char *buf)
                    385: {
                    386:        trace_index_mapping_t *tmap;
                    387:        unsigned len;
                    388:        trace_type_t *tptr, **prev;
                    389: 
                    390:        if (length < TRACE_INDEX_MAPPING_SIZE) {
                    391:                log_error ("short trace index mapping");
                    392:                return;
                    393:        }
                    394:        tmap = (trace_index_mapping_t *)buf;
                    395: 
                    396:        prev = &new_trace_types;
                    397:        for (tptr = new_trace_types; tptr; tptr = tptr -> next) {
                    398:                len = strlen (tptr -> name);
                    399:                if (len == length - TRACE_INDEX_MAPPING_SIZE &&
                    400:                    !memcmp (tptr -> name, tmap -> name, len)) {
                    401:                        tptr -> index = ntohl (tmap -> index);
                    402:                        trace_type_stash (tptr);
                    403:                        *prev = tptr -> next;
                    404:                        return;
                    405:                }
                    406:                prev = &tptr -> next;
                    407:        }
                    408:        
                    409:        log_error ("No registered trace type for type name %.*s",
                    410:                   (int)length - TRACE_INDEX_MAPPING_SIZE, tmap -> name);
                    411:        return;
                    412: }
                    413: 
                    414: void trace_index_stop_tracing (trace_type_t *ttype) { }
                    415: 
                    416: void trace_replay_init (void)
                    417: {
                    418:        trace_playback_flag = 1;
                    419: }
                    420: 
                    421: void trace_file_replay (const char *filename)
                    422: {
                    423:        tracepacket_t *tpkt = (tracepacket_t *)0;
                    424:        int status;
                    425:        char *buf = (char *)0;
                    426:        unsigned buflen;
                    427:        unsigned bufmax = 0;
                    428:        trace_type_t *ttype = (trace_type_t *)0;
                    429:        isc_result_t result;
                    430:        int len;
                    431: 
                    432:        traceinfile = fopen (filename, "r");
                    433:        if (!traceinfile) {
                    434:                log_error ("Can't open tracefile %s: %m", filename);
                    435:                return;
                    436:        }
                    437: #if defined (HAVE_SETFD)
                    438:        if (fcntl (fileno (traceinfile), F_SETFD, 1) < 0)
                    439:                log_error ("Can't set close-on-exec on %s: %m", filename);
                    440: #endif
                    441:        status = fread (&tracefile_header, 1,
                    442:                        sizeof tracefile_header, traceinfile);
                    443:        if (status < sizeof tracefile_header) {
                    444:                if (ferror (traceinfile))
                    445:                        log_error ("Error reading trace file header: %m");
                    446:                else
                    447:                        log_error ("Short read on trace file header: %d %ld.",
                    448:                                   status, (long)(sizeof tracefile_header));
                    449:                goto out;
                    450:        }
                    451:        tracefile_header.magic = ntohl (tracefile_header.magic);
                    452:        tracefile_header.version = ntohl (tracefile_header.version);
                    453:        tracefile_header.hlen = ntohl (tracefile_header.hlen);
                    454:        tracefile_header.phlen = ntohl (tracefile_header.phlen);
                    455: 
                    456:        if (tracefile_header.magic != TRACEFILE_MAGIC) {
                    457:                log_error ("%s: not a dhcp trace file.", filename);
                    458:                goto out;
                    459:        }
                    460:        if (tracefile_header.version > TRACEFILE_VERSION) {
                    461:                log_error ("tracefile version %ld > current %ld.",
                    462:                           (long int)tracefile_header.version,
                    463:                           (long int)TRACEFILE_VERSION);
                    464:                goto out;
                    465:        }
                    466:        if (tracefile_header.phlen < sizeof *tpkt) {
                    467:                log_error ("tracefile packet size too small - %ld < %ld",
                    468:                           (long int)tracefile_header.phlen,
                    469:                           (long int)sizeof *tpkt);
                    470:                goto out;
                    471:        }
                    472:        len = (sizeof tracefile_header) - tracefile_header.hlen;
                    473:        if (len < 0) {
                    474:                log_error ("tracefile header size too small - %ld < %ld",
                    475:                           (long int)tracefile_header.hlen,
                    476:                           (long int)sizeof tracefile_header);
                    477:                goto out;
                    478:        }
                    479:        if (len > 0) {
                    480:                status = fseek (traceinfile, (long)len, SEEK_CUR);
                    481:                if (status < 0) {
                    482:                        log_error ("can't seek past header: %m");
                    483:                        goto out;
                    484:                }
                    485:        }
                    486: 
                    487:        tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
                    488:        if (!tpkt) {
                    489:                log_error ("can't allocate trace packet header.");
                    490:                goto out;
                    491:        }
                    492: 
                    493:        while ((result = trace_get_next_packet (&ttype, tpkt, &buf, &buflen,
                    494:                                                &bufmax)) == ISC_R_SUCCESS) {
                    495:            (*ttype -> have_packet) (ttype, tpkt -> length, buf);
                    496:            ttype = (trace_type_t *)0;
                    497:        }
                    498:       out:
                    499:        fclose (traceinfile);
                    500:        if (buf)
                    501:                dfree (buf, MDL);
                    502:        if (tpkt)
                    503:                dfree (tpkt, MDL);
                    504: }
                    505: 
                    506: /* Get the next packet from the file.   If ttp points to a nonzero pointer
                    507:    to a trace type structure, check the next packet to see if it's of the
                    508:    expected type, and back off if not. */
                    509: 
                    510: isc_result_t trace_get_next_packet (trace_type_t **ttp,
                    511:                                    tracepacket_t *tpkt,
                    512:                                    char **buf, unsigned *buflen,
                    513:                                    unsigned *bufmax)
                    514: {
                    515:        trace_type_t *ttype;
                    516:        unsigned paylen;
                    517:        int status;
                    518:        fpos_t curpos;
                    519: 
                    520:        status = fgetpos (traceinfile, &curpos);
                    521:        if (status < 0)
                    522:                log_error ("Can't save tracefile position: %m");
                    523: 
                    524:        status = fread (tpkt, 1, (size_t)tracefile_header.phlen, traceinfile);
                    525:        if (status < tracefile_header.phlen) {
                    526:                if (ferror (traceinfile))
                    527:                        log_error ("Error reading trace packet header: %m");
                    528:                else if (status == 0)
                    529:                        return ISC_R_EOF;
                    530:                else
                    531:                        log_error ("Short read on trace packet header: "
                    532:                                   "%ld %ld.",
                    533:                                   (long int)status,
                    534:                                   (long int)tracefile_header.phlen);
                    535:                return ISC_R_PROTOCOLERROR;
                    536:        }
                    537: 
                    538:        /* Swap the packet. */
                    539:        tpkt -> type_index = ntohl (tpkt -> type_index);
                    540:        tpkt -> length = ntohl (tpkt -> length);
                    541:        tpkt -> when = ntohl (tpkt -> when);
                    542:        
                    543:        /* See if there's a handler for this packet type. */
                    544:        if (tpkt -> type_index < trace_type_count &&
                    545:            trace_types [tpkt -> type_index])
                    546:                ttype = trace_types [tpkt -> type_index];
                    547:        else {
                    548:                log_error ("Trace packet with unknown index %ld",
                    549:                           (long int)tpkt -> type_index);
                    550:                return ISC_R_PROTOCOLERROR;
                    551:        }
                    552: 
                    553:        /* If we were just hunting for the time marker, we've found it,
                    554:           so back up to the beginning of the packet and return its
                    555:           type. */
                    556:        if (ttp && *ttp == &trace_time_marker) {
                    557:                *ttp = ttype;
                    558:                status = fsetpos (traceinfile, &curpos);
                    559:                if (status < 0) {
                    560:                        log_error ("fsetpos in tracefile failed: %m");
                    561:                        return ISC_R_PROTOCOLERROR;
                    562:                }
                    563:                return ISC_R_EXISTS;
                    564:        }
                    565: 
                    566:        /* If we were supposed to get a particular kind of packet,
                    567:           check to see that we got the right kind. */
                    568:        if (ttp && *ttp && ttype != *ttp) {
                    569:                log_error ("Read packet type %s when expecting %s",
                    570:                           ttype -> name, (*ttp) -> name);
                    571:                status = fsetpos (traceinfile, &curpos);
                    572:                if (status < 0) {
                    573:                        log_error ("fsetpos in tracefile failed: %m");
                    574:                        return ISC_R_PROTOCOLERROR;
                    575:                }
                    576:                return ISC_R_UNEXPECTEDTOKEN;
                    577:        }
                    578: 
                    579:        paylen = tpkt -> length;
                    580:        if (paylen % 8)
                    581:                paylen += 8 - (tpkt -> length % 8);
                    582:        if (paylen > (*bufmax)) {
                    583:                if ((*buf))
                    584:                        dfree ((*buf), MDL);
                    585:                (*bufmax) = ((paylen + 1023) & ~1023U);
                    586:                (*buf) = dmalloc ((*bufmax), MDL);
                    587:                if (!(*buf)) {
                    588:                        log_error ("Can't allocate input buffer sized %d",
                    589:                                   (*bufmax));
                    590:                        return ISC_R_NOMEMORY;
                    591:                }
                    592:        }
                    593:        
                    594:        status = fread ((*buf), 1, paylen, traceinfile);
                    595:        if (status < paylen) {
                    596:                if (ferror (traceinfile))
                    597:                        log_error ("Error reading trace payload: %m");
                    598:                else
                    599:                        log_error ("Short read on trace payload: %d %d.",
                    600:                                   status, paylen);
                    601:                return ISC_R_PROTOCOLERROR;
                    602:        }
                    603: 
                    604:        /* Store the actual length of the payload. */
                    605:        *buflen = tpkt -> length;
                    606: 
                    607:        if (trace_set_time_hook)
                    608:                (*trace_set_time_hook) (tpkt -> when);
                    609: 
                    610:        if (ttp)
                    611:                *ttp = ttype;
                    612:        return ISC_R_SUCCESS;
                    613: }
                    614: 
                    615: isc_result_t trace_get_packet (trace_type_t **ttp,
                    616:                               unsigned *buflen, char **buf)
                    617: {
                    618:        tracepacket_t *tpkt;
                    619:        unsigned bufmax = 0;
                    620:        isc_result_t status;
                    621: 
                    622:        if (!buf || *buf)
                    623:                return ISC_R_INVALIDARG;
                    624: 
                    625:        tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
                    626:        if (!tpkt) {
                    627:                log_error ("can't allocate trace packet header.");
                    628:                return ISC_R_NOMEMORY;
                    629:        }
                    630: 
                    631:        status = trace_get_next_packet (ttp, tpkt, buf, buflen, &bufmax);
                    632: 
                    633:        dfree (tpkt, MDL);
                    634:        return status;
                    635: }
                    636: 
                    637: time_t trace_snoop_time (trace_type_t **ptp)
                    638: {
                    639:        tracepacket_t *tpkt;
                    640:        unsigned bufmax = 0;
                    641:        unsigned buflen = 0;
                    642:        char *buf = (char *)0;
                    643:        time_t result;
                    644:        trace_type_t *ttp;
                    645:        
                    646:        if (!ptp)
                    647:                ptp = &ttp;
                    648: 
                    649:        tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
                    650:        if (!tpkt) {
                    651:                log_error ("can't allocate trace packet header.");
                    652:                return ISC_R_NOMEMORY;
                    653:        }
                    654: 
                    655:        *ptp = &trace_time_marker;
                    656:        trace_get_next_packet (ptp, tpkt, &buf, &buflen, &bufmax);
                    657:        result = tpkt -> when;
                    658: 
                    659:        dfree (tpkt, MDL);
                    660:        return result;
                    661: }
                    662: 
                    663: /* Get a packet from the trace input file that contains a file with the
                    664:    specified name.   We don't hunt for the packet - it should be the next
                    665:    packet in the tracefile.   If it's not, or something else bad happens,
                    666:    return an error code. */
                    667: 
                    668: isc_result_t trace_get_file (trace_type_t *ttype,
                    669:                             const char *filename, unsigned *len, char **buf)
                    670: {
                    671:        fpos_t curpos;
                    672:        unsigned max = 0;
                    673:        tracepacket_t *tpkt;
                    674:        int status;
                    675:        isc_result_t result;
                    676: 
                    677:        /* Disallow some obvious bogosities. */
                    678:        if (!buf || !len || *buf)
                    679:                return ISC_R_INVALIDARG;
                    680: 
                    681:        /* Save file position in case of filename mismatch. */
                    682:        status = fgetpos (traceinfile, &curpos);
                    683:        if (status < 0)
                    684:                log_error ("Can't save tracefile position: %m");
                    685: 
                    686:        tpkt = dmalloc ((unsigned)tracefile_header.phlen, MDL);
                    687:        if (!tpkt) {
                    688:                log_error ("can't allocate trace packet header.");
                    689:                return ISC_R_NOMEMORY;
                    690:        }
                    691: 
                    692:        result = trace_get_next_packet (&ttype, tpkt, buf, len, &max);
                    693:        if (result != ISC_R_SUCCESS) {
                    694:                dfree (tpkt, MDL);
                    695:                if (*buf)
                    696:                        dfree (*buf, MDL);
                    697:                return result;
                    698:        }
                    699: 
                    700:        /* Make sure the filename is right. */
                    701:        if (strcmp (filename, *buf)) {
                    702:                log_error ("Read file %s when expecting %s", *buf, filename);
                    703:                status = fsetpos (traceinfile, &curpos);
                    704:                if (status < 0) {
                    705:                        log_error ("fsetpos in tracefile failed: %m");
                    706:                        dfree (tpkt, MDL);
                    707:                        dfree (*buf, MDL);
                    708:                        return ISC_R_PROTOCOLERROR;
                    709:                }
                    710:                return ISC_R_UNEXPECTEDTOKEN;
                    711:        }
                    712: 
                    713:        dfree (tpkt, MDL);
                    714:        return ISC_R_SUCCESS;
                    715: }
                    716: #endif /* TRACING */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>