source: lib/format_erf.c @ c69aecb

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c69aecb was c69aecb, checked in by Shane Alcock <salcock@…>, 6 years ago

Handle incomplete file reads in libtrace formats

Some file read function calls assumed that the full amount that was
asked for will be read from the file, which is not necessarily true
especially if the file was truncated.

  • Property mode set to 100644
File size: 22.8 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#define _GNU_SOURCE
36
37#include "config.h"
38#include "common.h"
39#include "libtrace.h"
40#include "libtrace_int.h"
41#include "format_helper.h"
42#include "format_erf.h"
43#include "wandio.h"
44
45#include <assert.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <stdio.h>
49#include <string.h>
50#include <stdlib.h>
51
52#ifdef WIN32
53#  include <io.h>
54#  include <share.h>
55#  define PATH_MAX _MAX_PATH
56#else
57#  include <netdb.h>
58#  ifndef PATH_MAX
59#       define PATH_MAX 4096
60#  endif
61#  include <sys/ioctl.h>
62#endif
63
64/* This format module deals with reading and writing ERF traces. ERF is the
65 * trace format developed by Endace for use by DAG hardware capture cards.
66 *
67 * ERF is not a live capture format.
68 *
69 */
70
71
72static struct libtrace_format_t erfformat;
73
74#define DATA(x) ((struct erf_format_data_t *)x->format_data)
75#define DATAOUT(x) ((struct erf_format_data_out_t *)x->format_data)
76
77#define IN_OPTIONS DATA(libtrace)->options
78#define OUTPUT DATAOUT(libtrace)
79#define OUT_OPTIONS DATAOUT(libtrace)->options
80
81/* "Global" data that is stored for each ERF input trace */
82struct erf_format_data_t {
83       
84        /* Index used for seeking within a trace */
85        struct {
86                /* The index itself */
87                io_t *index;
88                /* The offset of the index */
89                off_t index_len;
90                /* Indicates the existence of an index */
91                enum { INDEX_UNKNOWN=0, INDEX_NONE, INDEX_EXISTS } exists;
92        } seek;
93
94        /* Number of packets that were dropped during the capture */
95        uint64_t drops;
96
97        /* Config options for the input trace */
98        struct {
99                /* Flag indicating whether the event API should replicate the
100                 * time gaps between each packet or return a PACKET event for
101                 * each packet */
102                int real_time;
103        } options;
104};
105
106/* "Global" data that is stored for each ERF output trace */
107struct erf_format_data_out_t {
108
109        /* Config options for the output trace */
110        struct {
111                /* Compression level for the output file */
112                int level;
113                /* Compression type */
114                int compress_type;
115                /* File flags used to open the file, e.g. O_CREATE */
116                int fileflag;
117        } options;
118
119        /* The output file itself */
120        iow_t *file;
121       
122};
123
124typedef struct erf_index_t {
125        uint64_t timestamp;
126        uint64_t offset; 
127} erf_index_t;
128
129
130/* Ethernet packets have a 2 byte padding before the packet
131 * so that the IP header is aligned on a 32 bit boundary.
132 */
133static int erf_get_padding(const libtrace_packet_t *packet)
134{
135        if (packet->trace->format->type==TRACE_FORMAT_ERF) {
136                dag_record_t *erfptr = (dag_record_t *)packet->header;
137                switch(erfptr->type) {
138                        case TYPE_ETH:         
139                        case TYPE_DSM_COLOR_ETH:
140                                return 2;
141                        default:                return 0;
142                }
143        }
144        else {
145                switch(trace_get_link_type(packet)) {
146                        case TRACE_TYPE_ETH:    return 2;
147                        default:                return 0;
148                }
149        }
150}
151
152int erf_get_framing_length(const libtrace_packet_t *packet)
153{
154        return dag_record_size + erf_get_padding(packet);
155}
156
157/* Attempts to determine whether a given trace file is using the ERF format
158 *
159 * Returns 1 if the trace is probably ERF, 0 otherwise
160 */
161static int erf_probe_magic(io_t *io)
162{
163        char buffer[4096];
164        int len;
165        dag_record_t *erf;
166        len = wandio_peek(io, buffer, sizeof(buffer));
167        if (len < (int)dag_record_size) {
168                return 0; /* False */
169        }
170        erf = (dag_record_t *) buffer;
171        /* If the record is too short */
172        if (ntohs(erf->rlen) < dag_record_size) {
173                return 0;
174        }
175        /* There aren't any erf traces before 1995-01-01 */
176        if (bswap_le_to_host64(erf->ts) < 0x2f0539b000000000ULL) {
177                return 0;
178        }
179        /* And not pcap! */
180        if (bswap_le_to_host64(erf->ts) >>32 == 0xa1b2c3d4) {
181                return 0;
182        }
183        /* And not the other pcap! */
184        if (bswap_le_to_host64(erf->ts) >>32 == 0xd4c3b2a1) {
185                return 0;
186        }
187        /* Is this a proper typed packet */
188        if (erf->type > TYPE_AAL2) {
189                return 0;
190        }
191        /* We should put some more tests in here. */
192        /* Yeah, this is probably ERF */
193        return 1;
194}
195
196static int erf_init_input(libtrace_t *libtrace) 
197{
198        libtrace->format_data = malloc(sizeof(struct erf_format_data_t));
199       
200        IN_OPTIONS.real_time = 0;
201        DATA(libtrace)->drops = 0;
202       
203        return 0; /* success */
204}
205
206static int erf_config_input(libtrace_t *libtrace, trace_option_t option,
207                void *value) {
208
209        switch (option) {
210                case TRACE_OPTION_EVENT_REALTIME:
211                        IN_OPTIONS.real_time = *(int *)value;
212                        return 0;
213                case TRACE_OPTION_SNAPLEN:
214                case TRACE_OPTION_PROMISC:
215                case TRACE_OPTION_FILTER:
216                case TRACE_OPTION_META_FREQ:
217                        trace_set_err(libtrace, TRACE_ERR_OPTION_UNAVAIL,
218                                        "Unsupported option");
219                        return -1;
220                default:
221                        /* Unknown option */
222                        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
223                                        "Unknown option");
224                        return -1;
225        }
226}
227
228static int erf_start_input(libtrace_t *libtrace) 
229{
230        if (libtrace->io)
231                return 0; /* Success -- already done. */
232
233        libtrace->io = trace_open_file(libtrace);
234
235        if (!libtrace->io)
236                return -1;
237
238        DATA(libtrace)->drops = 0;
239        return 0; /* success */
240}
241
242/* Raw ERF is a special case -- we want to force libwandio to treat the file
243 * as uncompressed so we can't just use trace_open_file() */
244static int rawerf_start_input(libtrace_t *libtrace)
245{
246        if (libtrace->io)
247                return 0; 
248
249        libtrace->io = wandio_create_uncompressed(libtrace->uridata);
250
251        if (!libtrace->io) {
252                if (errno != 0) {
253                        trace_set_err(libtrace, errno, "Unable to open raw ERF file %s", libtrace->uridata);
254                }
255                return -1;
256        }
257
258        DATA(libtrace)->drops = 0;
259
260        return 0; /* success */
261}
262
263/* Binary search through the index to find the closest point before
264 * the packet.  Consider in future having a btree index perhaps?
265 */
266static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
267{
268        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
269        size_t min_off = 0;
270        off_t current;
271        erf_index_t record;
272        do {
273                current=(max_off+min_off)>>2;
274
275                wandio_seek(DATA(libtrace)->seek.index,
276                                (int64_t)(current*sizeof(record)),
277                                SEEK_SET);
278                wandio_read(DATA(libtrace)->seek.index,
279                                &record,sizeof(record));
280                if (record.timestamp < erfts) {
281                        min_off=current;
282                }
283                if (record.timestamp > erfts) {
284                        max_off=current;
285                }
286                if (record.timestamp == erfts)
287                        break;
288        } while(min_off<max_off);
289
290        /* If we've passed it, seek backwards.  This loop shouldn't
291         * execute more than twice.
292         */
293        do {
294                wandio_seek(DATA(libtrace)->seek.index,
295                                (int64_t)(current*sizeof(record)),SEEK_SET);
296                wandio_read(DATA(libtrace)->seek.index,
297                                &record,sizeof(record));
298                current--;
299        } while(record.timestamp>erfts);
300
301        /* We've found our location in the trace, now use it. */
302        wandio_seek(libtrace->io,(int64_t) record.offset,SEEK_SET);
303
304        return 0; /* success */
305}
306
307/* There is no index.  Seek through the entire trace from the start, nice
308 * and slowly.
309 */
310static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
311{
312        if (libtrace->io) {
313                wandio_destroy(libtrace->io);
314        }
315        libtrace->io = trace_open_file(libtrace);
316        if (!libtrace->io)
317                return -1;
318        return 0;
319}
320
321/* Seek within an ERF trace based on an ERF timestamp */
322static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
323{
324        libtrace_packet_t *packet;
325        off_t off = 0;
326
327        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
328                char buffer[PATH_MAX];
329                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
330                DATA(libtrace)->seek.index=wandio_create(buffer);
331                if (DATA(libtrace)->seek.index) {
332                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
333                }
334                else {
335                        DATA(libtrace)->seek.exists=INDEX_NONE;
336                }
337        }
338
339        /* If theres an index, use it to find the nearest packet that isn't
340         * after the time we're looking for.  If there is no index we need
341         * to seek slowly through the trace from the beginning.  Sigh.
342         */
343        switch(DATA(libtrace)->seek.exists) {
344                case INDEX_EXISTS:
345                        erf_fast_seek_start(libtrace,erfts);
346                        break;
347                case INDEX_NONE:
348                        erf_slow_seek_start(libtrace,erfts);
349                        break;
350                case INDEX_UNKNOWN:
351                        assert(0);
352                        break;
353        }
354
355        /* Now seek forward looking for the correct timestamp */
356        packet=trace_create_packet();
357        do {
358                trace_read_packet(libtrace,packet);
359                if (trace_get_erf_timestamp(packet)==erfts)
360                        break;
361                off=wandio_tell(libtrace->io);
362        } while(trace_get_erf_timestamp(packet)<erfts);
363
364        wandio_seek(libtrace->io,off,SEEK_SET);
365
366        return 0;
367}
368
369static int erf_init_output(libtrace_out_t *libtrace) {
370        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
371
372        OUT_OPTIONS.level = 0;
373        OUT_OPTIONS.compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
374        OUT_OPTIONS.fileflag = O_CREAT | O_WRONLY;
375        OUTPUT->file = 0;
376
377        return 0;
378}
379
380static int erf_config_output(libtrace_out_t *libtrace, 
381                trace_option_output_t option, void *value) {
382
383        switch (option) {
384                case TRACE_OPTION_OUTPUT_COMPRESS:
385                        OUT_OPTIONS.level = *(int*)value;
386                        return 0;
387                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
388                        OUT_OPTIONS.compress_type = *(int*)value;
389                        return 0;
390                case TRACE_OPTION_OUTPUT_FILEFLAGS:
391                        OUT_OPTIONS.fileflag = *(int*)value;
392                        return 0;
393                default:
394                        /* Unknown option */
395                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
396                                        "Unknown option");
397                        return -1;
398        }
399}
400
401
402
403static int erf_fin_input(libtrace_t *libtrace) {
404        if (libtrace->io)
405                wandio_destroy(libtrace->io);
406        free(libtrace->format_data);
407        return 0;
408}
409
410static int erf_fin_output(libtrace_out_t *libtrace) {
411        if (OUTPUT->file)
412                wandio_wdestroy(OUTPUT->file);
413        free(libtrace->format_data);
414        return 0;
415}
416 
417static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
418                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
419       
420        dag_record_t *erfptr;
421       
422        if (packet->buffer != buffer && 
423                packet->buf_control == TRACE_CTRL_PACKET) {
424                free(packet->buffer);
425        }
426
427        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
428                packet->buf_control = TRACE_CTRL_PACKET;
429        } else
430                packet->buf_control = TRACE_CTRL_EXTERNAL;
431       
432       
433        packet->type = rt_type;
434        packet->buffer = buffer;
435        packet->header = buffer;
436        erfptr = (dag_record_t *)packet->buffer;
437        if (erfptr->flags.rxerror == 1) {
438                packet->payload = NULL;
439        } else {
440                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
441        }
442       
443        if (libtrace->format_data == NULL) {
444                /* Allocates the format_data structure */
445                if (erf_init_input(libtrace)) 
446                        return -1;
447        }
448
449        /* Check for loss */
450        if (erfptr->type == TYPE_DSM_COLOR_ETH) {
451                /* No idea how we get this yet */
452
453        } else if (erfptr->lctr) {
454                DATA(libtrace)->drops += ntohs(erfptr->lctr);
455        }
456
457        return 0;
458}
459
460static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
461        int numbytes;
462        unsigned int size;
463        void *buffer2 = packet->buffer;
464        unsigned int rlen;
465        uint32_t flags = 0;
466       
467       
468        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
469                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
470                if (!packet->buffer) {
471                        trace_set_err(libtrace, errno, 
472                                        "Cannot allocate memory");
473                        return -1;
474                }
475        }
476
477        flags |= TRACE_PREP_OWN_BUFFER; 
478       
479        if ((numbytes=wandio_read(libtrace->io,
480                                        packet->buffer,
481                                        (size_t)dag_record_size)) == -1) {
482                trace_set_err(libtrace,errno,"reading ERF file");
483                return -1;
484        }
485        /* EOF */
486        if (numbytes == 0) {
487                return 0;
488        }
489
490        if (numbytes < (int)dag_record_size) {
491                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF header");
492                return -1;
493        }
494
495        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
496        buffer2 = (char*)packet->buffer + dag_record_size;
497        size = rlen - dag_record_size;
498
499        if (size >= LIBTRACE_PACKET_BUFSIZE) {
500                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
501                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
502                                size);
503                return -1;
504        }
505
506        /* Unknown/corrupt */
507        if (((dag_record_t *)packet->buffer)->type >= TYPE_RAW_LINK) {
508                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
509                                "Corrupt or Unknown ERF type");
510                return -1;
511        }
512       
513        /* read in the rest of the packet */
514        if ((numbytes=wandio_read(libtrace->io,
515                                        buffer2,
516                                        (size_t)size)) != (int)size) {
517                if (numbytes==-1) {
518                        trace_set_err(libtrace,errno, "read(%s)", 
519                                        libtrace->uridata);
520                        return -1;
521                }
522                trace_set_err(libtrace,EIO,
523                                "Truncated packet (wanted %d, got %d)", 
524                                size, numbytes);
525                /* Failed to read the full packet?  must be EOF */
526                return -1;
527        }
528
529        if (numbytes < (int)size) {
530                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Incomplete ERF record");
531                return -1;
532        }
533       
534        if (erf_prepare_packet(libtrace, packet, packet->buffer, 
535                                TRACE_RT_DATA_ERF, flags))
536                return -1;
537       
538        return rlen;
539}
540
541static int erf_dump_packet(libtrace_out_t *libtrace,
542                dag_record_t *erfptr, unsigned int pad, void *buffer) {
543        int numbytes = 0;
544        int size;
545
546        if ((numbytes = 
547                wandio_wwrite(OUTPUT->file, 
548                                erfptr,
549                                (size_t)(dag_record_size + pad))) 
550                        != (int)(dag_record_size+pad)) {
551                trace_set_err_out(libtrace,errno,
552                                "write(%s)",libtrace->uridata);
553                return -1;
554        }
555
556        size=ntohs(erfptr->rlen)-(dag_record_size+pad);
557        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)size);
558        if (numbytes != size) {
559                trace_set_err_out(libtrace,errno,
560                                "write(%s)",libtrace->uridata);
561                return -1;
562        }
563        return numbytes + pad + dag_record_size;
564}
565
566static int erf_start_output(libtrace_out_t *libtrace)
567{
568        OUTPUT->file = trace_open_file_out(libtrace,
569                        OUT_OPTIONS.compress_type,
570                        OUT_OPTIONS.level,
571                        OUT_OPTIONS.fileflag);
572
573        if (!OUTPUT->file) {
574                return -1;
575        }
576        return 0;
577}
578
579static bool find_compatible_linktype(libtrace_out_t *libtrace,
580                                libtrace_packet_t *packet)
581{
582        /* Keep trying to simplify the packet until we can find
583         * something we can do with it */
584        do {
585                char type=libtrace_to_erf_type(trace_get_link_type(packet));
586
587                /* Success */
588                if (type != (char)-1)
589                        return true;
590
591                if (!demote_packet(packet)) {
592                        trace_set_err_out(libtrace,
593                                        TRACE_ERR_NO_CONVERSION,
594                                        "No erf type for packet (%i)",
595                                        trace_get_link_type(packet));
596                        return false;
597                }
598
599        } while(1);
600
601        return true;
602}
603               
604static int erf_write_packet(libtrace_out_t *libtrace, 
605                libtrace_packet_t *packet) 
606{
607        int numbytes = 0;
608        unsigned int pad = 0;
609        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
610        void *payload = packet->payload;
611
612        assert(OUTPUT->file);
613
614        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
615                return 0;
616
617        if (!packet->header) {
618                return -1;
619        }
620       
621        pad = erf_get_padding(packet);
622
623        /* If we've had an rxerror, we have no payload to write - fix
624         * rlen to be the correct length
625         */
626        /* I Think this is bogus, we should somehow figure out
627         * a way to write out the payload even if it is gibberish -- Perry */
628        if (payload == NULL) {
629                dag_hdr->rlen = htons(dag_record_size + pad);
630               
631        } 
632       
633        if (packet->type == TRACE_RT_DATA_ERF) {
634                        numbytes = erf_dump_packet(libtrace,
635                                (dag_record_t *)packet->header,
636                                pad,
637                                payload
638                                );
639        } else {
640                dag_record_t erfhdr;
641                int rlen;
642                /* convert format - build up a new erf header */
643                /* Timestamp */
644                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
645
646                /* Flags. Can't do this */
647                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
648                if (trace_get_direction(packet)!=TRACE_DIR_UNKNOWN)
649                        erfhdr.flags.iface = trace_get_direction(packet);
650
651                if (!find_compatible_linktype(libtrace,packet))
652                        return -1;
653
654                payload=packet->payload;
655                pad = erf_get_padding(packet);
656
657                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
658
659                /* Packet length (rlen includes format overhead) */
660                assert(trace_get_capture_length(packet)>0 
661                                && trace_get_capture_length(packet)<=65536);
662                assert(erf_get_framing_length(packet)>0 
663                                && trace_get_framing_length(packet)<=65536);
664
665                rlen = trace_get_capture_length(packet) + 
666                                erf_get_framing_length(packet);
667                assert(rlen > 0 && rlen <= 65536);
668                erfhdr.rlen = htons(rlen);
669                /* loss counter. Can't do this */
670                erfhdr.lctr = 0;
671                /* Wire length, does not include padding! */
672                erfhdr.wlen = htons(trace_get_wire_length(packet));
673
674                /* Write it out */
675                numbytes = erf_dump_packet(libtrace,
676                                &erfhdr,
677                                pad,
678                                payload);
679        }
680        return numbytes;
681}
682
683libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
684        dag_record_t *erfptr = 0;
685        erfptr = (dag_record_t *)packet->header;
686        if (erfptr->type != TYPE_LEGACY)
687                return erf_type_to_libtrace(erfptr->type);
688        else {
689                /* Sigh, lets start wildly guessing */
690                if (((char*)packet->payload)[4]==0x45)
691                        return TRACE_TYPE_PPP;
692                return ~0;
693        }
694}
695
696libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
697        dag_record_t *erfptr = 0;
698        erfptr = (dag_record_t *)packet->header;
699        return erfptr->flags.iface;
700}
701
702libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
703        dag_record_t *erfptr = 0;
704        erfptr = (dag_record_t *)packet->header;
705        erfptr->flags.iface = direction;
706        return erfptr->flags.iface;
707}
708
709uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
710        dag_record_t *erfptr = 0;
711        erfptr = (dag_record_t *)packet->header;
712        return bswap_le_to_host64(erfptr->ts);
713}
714
715int erf_get_capture_length(const libtrace_packet_t *packet) {
716        dag_record_t *erfptr = 0;
717        int caplen;
718        if (packet->payload == NULL)
719                return 0; 
720       
721        erfptr = (dag_record_t *)packet->header;
722        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
723        if (ntohs(erfptr->wlen) < caplen)
724                return ntohs(erfptr->wlen);
725
726        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
727}
728
729int erf_get_wire_length(const libtrace_packet_t *packet) {
730        dag_record_t *erfptr = 0;
731        erfptr = (dag_record_t *)packet->header;
732        return ntohs(erfptr->wlen);
733}
734
735size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
736        dag_record_t *erfptr = 0;
737        assert(packet);
738        if(size  > trace_get_capture_length(packet)) {
739                /* Can't make a packet larger */
740                return trace_get_capture_length(packet);
741        }
742        /* Reset cached capture length - otherwise we will both return the
743         * wrong value here and subsequent get_capture_length() calls will
744         * return the wrong value. */
745        packet->capture_length = -1;
746        erfptr = (dag_record_t *)packet->header;
747        erfptr->rlen = htons(size + erf_get_framing_length(packet));
748        return trace_get_capture_length(packet);
749}
750
751static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
752        struct libtrace_eventobj_t event = {0,0,0.0,0};
753       
754        /* If we are being told to replay packets as fast as possible, then
755         * we just need to read and return the next packet in the trace */
756        if (IN_OPTIONS.real_time) {
757                event.size = trace_read_packet(libtrace, packet);
758                if (event.size < 1)
759                        event.type = TRACE_EVENT_TERMINATE;
760                else
761                        event.type = TRACE_EVENT_PACKET;
762                return event;
763               
764        } else {
765                /* Otherwise, use the generic event function */
766                return trace_event_trace(libtrace, packet);
767        }
768       
769}
770
771static uint64_t erf_get_dropped_packets(libtrace_t *trace)
772{
773        if (trace->format_data == NULL)
774                return (uint64_t)-1;
775        return DATA(trace)->drops;
776}
777
778static void erf_help(void) {
779        printf("erf format module: $Revision: 1752 $\n");
780        printf("Supported input URIs:\n");
781        printf("\terf:/path/to/file\t(uncompressed)\n");
782        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
783        printf("\terf:-\t(stdin, either compressed or not)\n");
784        printf("\terf:/path/to/socket\n");
785        printf("\n");
786        printf("\te.g.: erf:/tmp/trace\n");
787        printf("\n");
788        printf("Supported output URIs:\n");
789        printf("\terf:path/to/file\t(uncompressed)\n");
790        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
791        printf("\terf:-\t(stdout, either compressed or not)\n");
792        printf("\n");
793        printf("\te.g.: erf:/tmp/trace\n");
794        printf("\n");
795
796       
797}
798
799static struct libtrace_format_t erfformat = {
800        "erf",
801        "$Id$",
802        TRACE_FORMAT_ERF,
803        NULL,                           /* probe filename */
804        erf_probe_magic,                /* probe magic */
805        erf_init_input,                 /* init_input */       
806        erf_config_input,               /* config_input */
807        erf_start_input,                /* start_input */
808        NULL,                           /* pause_input */
809        erf_init_output,                /* init_output */
810        erf_config_output,              /* config_output */
811        erf_start_output,               /* start_output */
812        erf_fin_input,                  /* fin_input */
813        erf_fin_output,                 /* fin_output */
814        erf_read_packet,                /* read_packet */
815        erf_prepare_packet,             /* prepare_packet */
816        NULL,                           /* fin_packet */
817        erf_write_packet,               /* write_packet */
818        erf_get_link_type,              /* get_link_type */
819        erf_get_direction,              /* get_direction */
820        erf_set_direction,              /* set_direction */
821        erf_get_erf_timestamp,          /* get_erf_timestamp */
822        NULL,                           /* get_timeval */
823        NULL,                           /* get_timespec */
824        NULL,                           /* get_seconds */
825        erf_seek_erf,                   /* seek_erf */
826        NULL,                           /* seek_timeval */
827        NULL,                           /* seek_seconds */
828        erf_get_capture_length,         /* get_capture_length */
829        erf_get_wire_length,            /* get_wire_length */
830        erf_get_framing_length,         /* get_framing_length */
831        erf_set_capture_length,         /* set_capture_length */
832        NULL,                           /* get_received_packets */
833        NULL,                           /* get_filtered_packets */
834        erf_get_dropped_packets,        /* get_dropped_packets */
835        NULL,                           /* get_captured_packets */
836        NULL,                           /* get_fd */
837        erf_event,                      /* trace_event */
838        erf_help,                       /* help */
839        NULL                            /* next pointer */
840};
841
842static struct libtrace_format_t rawerfformat = {
843        "rawerf",
844        "$Id$",
845        TRACE_FORMAT_RAWERF,
846        NULL,                           /* probe filename */
847        NULL,           /* probe magic */
848        erf_init_input,                 /* init_input */       
849        erf_config_input,               /* config_input */
850        rawerf_start_input,             /* start_input */
851        NULL,                           /* pause_input */
852        erf_init_output,                /* init_output */
853        erf_config_output,              /* config_output */
854        erf_start_output,               /* start_output */
855        erf_fin_input,                  /* fin_input */
856        erf_fin_output,                 /* fin_output */
857        erf_read_packet,                /* read_packet */
858        erf_prepare_packet,             /* prepare_packet */
859        NULL,                           /* fin_packet */
860        erf_write_packet,               /* write_packet */
861        erf_get_link_type,              /* get_link_type */
862        erf_get_direction,              /* get_direction */
863        erf_set_direction,              /* set_direction */
864        erf_get_erf_timestamp,          /* get_erf_timestamp */
865        NULL,                           /* get_timeval */
866        NULL,                           /* get_timespec */
867        NULL,                           /* get_seconds */
868        erf_seek_erf,                   /* seek_erf */
869        NULL,                           /* seek_timeval */
870        NULL,                           /* seek_seconds */
871        erf_get_capture_length,         /* get_capture_length */
872        erf_get_wire_length,            /* get_wire_length */
873        erf_get_framing_length,         /* get_framing_length */
874        erf_set_capture_length,         /* set_capture_length */
875        NULL,                           /* get_received_packets */
876        NULL,                           /* get_filtered_packets */
877        erf_get_dropped_packets,        /* get_dropped_packets */
878        NULL,                           /* get_captured_packets */
879        NULL,                           /* get_fd */
880        erf_event,                      /* trace_event */
881        erf_help,                       /* help */
882        NULL                            /* next pointer */
883};
884
885
886
887void erf_constructor(void) {
888        register_format(&erfformat);
889        register_format(&rawerfformat);
890}
Note: See TracBrowser for help on using the repository browser.