source: lib/format_erf.c @ d57ae6f

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

Added a new format: rawerf. This is a special format that will force ERF files to be opened and read without going through the compression autodetection. It will only work for uncompressed ERF files.

This should be a handy option for people who are working with lots of uncompressed ERF files -- running the compression autodetection against uncompressed ERF traces can very occasionally produce a false positive, i.e. decide the file is compressed. By skipping the autodetection and forcing the traces to be read as uncompressed ERF, the threat of this bug will go away.

  • Property mode set to 100644
File size: 22.6 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        printf("Calling erf_start_input\n");
240
241        return 0; /* success */
242}
243
244/* Raw ERF is a special case -- we want to force libwandio to treat the file
245 * as uncompressed so we can't just use trace_open_file() */
246static int rawerf_start_input(libtrace_t *libtrace)
247{
248        if (libtrace->io)
249                wandio_destroy(libtrace->io); 
250
251        libtrace->io = wandio_create_uncompressed(libtrace->uridata);
252
253        if (!libtrace->io) {
254                if (errno != 0) {
255                        trace_set_err(libtrace, errno, "Unable to open raw ERF file %s", libtrace->uridata);
256                }
257                return -1;
258        }
259
260        DATA(libtrace)->drops = 0;
261
262        return 0; /* success */
263}
264
265/* Binary search through the index to find the closest point before
266 * the packet.  Consider in future having a btree index perhaps?
267 */
268static int erf_fast_seek_start(libtrace_t *libtrace,uint64_t erfts)
269{
270        size_t max_off = DATA(libtrace)->seek.index_len/sizeof(erf_index_t);
271        size_t min_off = 0;
272        off_t current;
273        erf_index_t record;
274        do {
275                current=(max_off+min_off)>>2;
276
277                wandio_seek(DATA(libtrace)->seek.index,
278                                (int64_t)(current*sizeof(record)),
279                                SEEK_SET);
280                wandio_read(DATA(libtrace)->seek.index,
281                                &record,sizeof(record));
282                if (record.timestamp < erfts) {
283                        min_off=current;
284                }
285                if (record.timestamp > erfts) {
286                        max_off=current;
287                }
288                if (record.timestamp == erfts)
289                        break;
290        } while(min_off<max_off);
291
292        /* If we've passed it, seek backwards.  This loop shouldn't
293         * execute more than twice.
294         */
295        do {
296                wandio_seek(DATA(libtrace)->seek.index,
297                                (int64_t)(current*sizeof(record)),SEEK_SET);
298                wandio_read(DATA(libtrace)->seek.index,
299                                &record,sizeof(record));
300                current--;
301        } while(record.timestamp>erfts);
302
303        /* We've found our location in the trace, now use it. */
304        wandio_seek(libtrace->io,(int64_t) record.offset,SEEK_SET);
305
306        return 0; /* success */
307}
308
309/* There is no index.  Seek through the entire trace from the start, nice
310 * and slowly.
311 */
312static int erf_slow_seek_start(libtrace_t *libtrace,uint64_t erfts UNUSED)
313{
314        if (libtrace->io) {
315                wandio_destroy(libtrace->io);
316        }
317        libtrace->io = trace_open_file(libtrace);
318        if (!libtrace->io)
319                return -1;
320        return 0;
321}
322
323/* Seek within an ERF trace based on an ERF timestamp */
324static int erf_seek_erf(libtrace_t *libtrace,uint64_t erfts)
325{
326        libtrace_packet_t *packet;
327        off_t off = 0;
328
329        if (DATA(libtrace)->seek.exists==INDEX_UNKNOWN) {
330                char buffer[PATH_MAX];
331                snprintf(buffer,sizeof(buffer),"%s.idx",libtrace->uridata);
332                DATA(libtrace)->seek.index=wandio_create(buffer);
333                if (DATA(libtrace)->seek.index) {
334                        DATA(libtrace)->seek.exists=INDEX_EXISTS;
335                }
336                else {
337                        DATA(libtrace)->seek.exists=INDEX_NONE;
338                }
339        }
340
341        /* If theres an index, use it to find the nearest packet that isn't
342         * after the time we're looking for.  If there is no index we need
343         * to seek slowly through the trace from the beginning.  Sigh.
344         */
345        switch(DATA(libtrace)->seek.exists) {
346                case INDEX_EXISTS:
347                        erf_fast_seek_start(libtrace,erfts);
348                        break;
349                case INDEX_NONE:
350                        erf_slow_seek_start(libtrace,erfts);
351                        break;
352                case INDEX_UNKNOWN:
353                        assert(0);
354                        break;
355        }
356
357        /* Now seek forward looking for the correct timestamp */
358        packet=trace_create_packet();
359        do {
360                trace_read_packet(libtrace,packet);
361                if (trace_get_erf_timestamp(packet)==erfts)
362                        break;
363                off=wandio_tell(libtrace->io);
364        } while(trace_get_erf_timestamp(packet)<erfts);
365
366        wandio_seek(libtrace->io,off,SEEK_SET);
367
368        return 0;
369}
370
371static int erf_init_output(libtrace_out_t *libtrace) {
372        libtrace->format_data = malloc(sizeof(struct erf_format_data_out_t));
373
374        OUT_OPTIONS.level = 0;
375        OUT_OPTIONS.compress_type = TRACE_OPTION_COMPRESSTYPE_NONE;
376        OUT_OPTIONS.fileflag = O_CREAT | O_WRONLY;
377        OUTPUT->file = 0;
378
379        return 0;
380}
381
382static int erf_config_output(libtrace_out_t *libtrace, 
383                trace_option_output_t option, void *value) {
384
385        switch (option) {
386                case TRACE_OPTION_OUTPUT_COMPRESS:
387                        OUT_OPTIONS.level = *(int*)value;
388                        return 0;
389                case TRACE_OPTION_OUTPUT_COMPRESSTYPE:
390                        OUT_OPTIONS.compress_type = *(int*)value;
391                        return 0;
392                case TRACE_OPTION_OUTPUT_FILEFLAGS:
393                        OUT_OPTIONS.fileflag = *(int*)value;
394                        return 0;
395                default:
396                        /* Unknown option */
397                        trace_set_err_out(libtrace,TRACE_ERR_UNKNOWN_OPTION,
398                                        "Unknown option");
399                        return -1;
400        }
401}
402
403
404
405static int erf_fin_input(libtrace_t *libtrace) {
406        if (libtrace->io)
407                wandio_destroy(libtrace->io);
408        free(libtrace->format_data);
409        return 0;
410}
411
412static int erf_fin_output(libtrace_out_t *libtrace) {
413        if (OUTPUT->file)
414                wandio_wdestroy(OUTPUT->file);
415        free(libtrace->format_data);
416        return 0;
417}
418 
419static int erf_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
420                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
421       
422        dag_record_t *erfptr;
423       
424        if (packet->buffer != buffer && 
425                packet->buf_control == TRACE_CTRL_PACKET) {
426                free(packet->buffer);
427        }
428
429        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
430                packet->buf_control = TRACE_CTRL_PACKET;
431        } else
432                packet->buf_control = TRACE_CTRL_EXTERNAL;
433       
434       
435        packet->type = rt_type;
436        packet->buffer = buffer;
437        packet->header = buffer;
438        erfptr = (dag_record_t *)packet->buffer;
439        if (erfptr->flags.rxerror == 1) {
440                packet->payload = NULL;
441        } else {
442                packet->payload = (char*)packet->buffer + erf_get_framing_length(packet);
443        }
444       
445        if (libtrace->format_data == NULL) {
446                /* Allocates the format_data structure */
447                if (erf_init_input(libtrace)) 
448                        return -1;
449        }
450
451        /* Check for loss */
452        if (erfptr->type == TYPE_DSM_COLOR_ETH) {
453                /* No idea how we get this yet */
454
455        } else if (erfptr->lctr) {
456                DATA(libtrace)->drops += ntohs(erfptr->lctr);
457        }
458
459        return 0;
460}
461
462static int erf_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
463        int numbytes;
464        unsigned int size;
465        void *buffer2 = packet->buffer;
466        unsigned int rlen;
467        uint32_t flags = 0;
468       
469       
470        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
471                packet->buffer = malloc((size_t)LIBTRACE_PACKET_BUFSIZE);
472                if (!packet->buffer) {
473                        trace_set_err(libtrace, errno, 
474                                        "Cannot allocate memory");
475                        return -1;
476                }
477        }
478
479        flags |= TRACE_PREP_OWN_BUFFER; 
480       
481        if ((numbytes=wandio_read(libtrace->io,
482                                        packet->buffer,
483                                        (size_t)dag_record_size)) == -1) {
484                trace_set_err(libtrace,errno,"read(%s)",
485                                libtrace->uridata);
486                return -1;
487        }
488        /* EOF */
489        if (numbytes == 0) {
490                return 0;
491        }
492
493        rlen = ntohs(((dag_record_t *)packet->buffer)->rlen);
494        buffer2 = (char*)packet->buffer + dag_record_size;
495        size = rlen - dag_record_size;
496
497        if (size >= LIBTRACE_PACKET_BUFSIZE) {
498                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
499                                "Packet size %u larger than supported by libtrace - packet is probably corrupt", 
500                                size);
501                return -1;
502        }
503
504        /* Unknown/corrupt */
505        if (((dag_record_t *)packet->buffer)->type >= TYPE_RAW_LINK) {
506                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
507                                "Corrupt or Unknown ERF type");
508                return -1;
509        }
510       
511        /* read in the rest of the packet */
512        if ((numbytes=wandio_read(libtrace->io,
513                                        buffer2,
514                                        (size_t)size)) != (int)size) {
515                if (numbytes==-1) {
516                        trace_set_err(libtrace,errno, "read(%s)", 
517                                        libtrace->uridata);
518                        return -1;
519                }
520                trace_set_err(libtrace,EIO,
521                                "Truncated packet (wanted %d, got %d)", 
522                                size, numbytes);
523                /* Failed to read the full packet?  must be EOF */
524                return -1;
525        }
526       
527        if (erf_prepare_packet(libtrace, packet, packet->buffer, 
528                                TRACE_RT_DATA_ERF, flags))
529                return -1;
530       
531        return rlen;
532}
533
534static int erf_dump_packet(libtrace_out_t *libtrace,
535                dag_record_t *erfptr, unsigned int pad, void *buffer) {
536        int numbytes = 0;
537        int size;
538
539        if ((numbytes = 
540                wandio_wwrite(OUTPUT->file, 
541                                erfptr,
542                                (size_t)(dag_record_size + pad))) 
543                        != (int)(dag_record_size+pad)) {
544                trace_set_err_out(libtrace,errno,
545                                "write(%s)",libtrace->uridata);
546                return -1;
547        }
548
549        size=ntohs(erfptr->rlen)-(dag_record_size+pad);
550        numbytes=wandio_wwrite(OUTPUT->file, buffer, (size_t)size);
551        if (numbytes != size) {
552                trace_set_err_out(libtrace,errno,
553                                "write(%s)",libtrace->uridata);
554                return -1;
555        }
556        return numbytes + pad + dag_record_size;
557}
558
559static int erf_start_output(libtrace_out_t *libtrace)
560{
561        OUTPUT->file = trace_open_file_out(libtrace,
562                        OUT_OPTIONS.compress_type,
563                        OUT_OPTIONS.level,
564                        OUT_OPTIONS.fileflag);
565
566        if (!OUTPUT->file) {
567                return -1;
568        }
569        return 0;
570}
571
572static bool find_compatible_linktype(libtrace_out_t *libtrace,
573                                libtrace_packet_t *packet)
574{
575        /* Keep trying to simplify the packet until we can find
576         * something we can do with it */
577        do {
578                char type=libtrace_to_erf_type(trace_get_link_type(packet));
579
580                /* Success */
581                if (type != (char)-1)
582                        return true;
583
584                if (!demote_packet(packet)) {
585                        trace_set_err_out(libtrace,
586                                        TRACE_ERR_NO_CONVERSION,
587                                        "No erf type for packet (%i)",
588                                        trace_get_link_type(packet));
589                        return false;
590                }
591
592        } while(1);
593
594        return true;
595}
596               
597static int erf_write_packet(libtrace_out_t *libtrace, 
598                libtrace_packet_t *packet) 
599{
600        int numbytes = 0;
601        unsigned int pad = 0;
602        dag_record_t *dag_hdr = (dag_record_t *)packet->header;
603        void *payload = packet->payload;
604
605        assert(OUTPUT->file);
606
607        if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA)
608                return 0;
609
610        if (!packet->header) {
611                return -1;
612        }
613       
614        pad = erf_get_padding(packet);
615
616        /* If we've had an rxerror, we have no payload to write - fix
617         * rlen to be the correct length
618         */
619        /* I Think this is bogus, we should somehow figure out
620         * a way to write out the payload even if it is gibberish -- Perry */
621        if (payload == NULL) {
622                dag_hdr->rlen = htons(dag_record_size + pad);
623               
624        } 
625       
626        if (packet->type == TRACE_RT_DATA_ERF) {
627                        numbytes = erf_dump_packet(libtrace,
628                                (dag_record_t *)packet->header,
629                                pad,
630                                payload
631                                );
632        } else {
633                dag_record_t erfhdr;
634                int rlen;
635                /* convert format - build up a new erf header */
636                /* Timestamp */
637                erfhdr.ts = bswap_host_to_le64(trace_get_erf_timestamp(packet));
638
639                /* Flags. Can't do this */
640                memset(&erfhdr.flags,1,sizeof(erfhdr.flags));
641                if (trace_get_direction(packet)!=~0U)
642                        erfhdr.flags.iface = trace_get_direction(packet);
643
644                if (!find_compatible_linktype(libtrace,packet))
645                        return -1;
646
647                payload=packet->payload;
648                pad = erf_get_padding(packet);
649
650                erfhdr.type = libtrace_to_erf_type(trace_get_link_type(packet));
651
652                /* Packet length (rlen includes format overhead) */
653                assert(trace_get_capture_length(packet)>0 
654                                && trace_get_capture_length(packet)<=65536);
655                assert(erf_get_framing_length(packet)>0 
656                                && trace_get_framing_length(packet)<=65536);
657
658                rlen = trace_get_capture_length(packet) + 
659                                erf_get_framing_length(packet);
660                assert(rlen > 0 && rlen <= 65536);
661                erfhdr.rlen = htons(rlen);
662                /* loss counter. Can't do this */
663                erfhdr.lctr = 0;
664                /* Wire length, does not include padding! */
665                erfhdr.wlen = htons(trace_get_wire_length(packet));
666
667                /* Write it out */
668                numbytes = erf_dump_packet(libtrace,
669                                &erfhdr,
670                                pad,
671                                payload);
672        }
673        return numbytes;
674}
675
676libtrace_linktype_t erf_get_link_type(const libtrace_packet_t *packet) {
677        dag_record_t *erfptr = 0;
678        erfptr = (dag_record_t *)packet->header;
679        if (erfptr->type != TYPE_LEGACY)
680                return erf_type_to_libtrace(erfptr->type);
681        else {
682                /* Sigh, lets start wildly guessing */
683                if (((char*)packet->payload)[4]==0x45)
684                        return TRACE_TYPE_PPP;
685                return ~0;
686        }
687}
688
689libtrace_direction_t erf_get_direction(const libtrace_packet_t *packet) {
690        dag_record_t *erfptr = 0;
691        erfptr = (dag_record_t *)packet->header;
692        return erfptr->flags.iface;
693}
694
695libtrace_direction_t erf_set_direction(libtrace_packet_t *packet, libtrace_direction_t direction) {
696        dag_record_t *erfptr = 0;
697        erfptr = (dag_record_t *)packet->header;
698        erfptr->flags.iface = direction;
699        return erfptr->flags.iface;
700}
701
702uint64_t erf_get_erf_timestamp(const libtrace_packet_t *packet) {
703        dag_record_t *erfptr = 0;
704        erfptr = (dag_record_t *)packet->header;
705        return bswap_le_to_host64(erfptr->ts);
706}
707
708int erf_get_capture_length(const libtrace_packet_t *packet) {
709        dag_record_t *erfptr = 0;
710        int caplen;
711        if (packet->payload == NULL)
712                return 0; 
713       
714        erfptr = (dag_record_t *)packet->header;
715        caplen = ntohs(erfptr->rlen) - erf_get_framing_length(packet);
716        if (ntohs(erfptr->wlen) < caplen)
717                return ntohs(erfptr->wlen);
718
719        return (ntohs(erfptr->rlen) - erf_get_framing_length(packet));
720}
721
722int erf_get_wire_length(const libtrace_packet_t *packet) {
723        dag_record_t *erfptr = 0;
724        erfptr = (dag_record_t *)packet->header;
725        return ntohs(erfptr->wlen);
726}
727
728size_t erf_set_capture_length(libtrace_packet_t *packet, size_t size) {
729        dag_record_t *erfptr = 0;
730        assert(packet);
731        if(size  > trace_get_capture_length(packet)) {
732                /* Can't make a packet larger */
733                return trace_get_capture_length(packet);
734        }
735        /* Reset cached capture length - otherwise we will both return the
736         * wrong value here and subsequent get_capture_length() calls will
737         * return the wrong value. */
738        packet->capture_length = -1;
739        erfptr = (dag_record_t *)packet->header;
740        erfptr->rlen = htons(size + erf_get_framing_length(packet));
741        return trace_get_capture_length(packet);
742}
743
744static struct libtrace_eventobj_t erf_event(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
745        struct libtrace_eventobj_t event = {0,0,0.0,0};
746       
747        /* If we are being told to replay packets as fast as possible, then
748         * we just need to read and return the next packet in the trace */
749        if (IN_OPTIONS.real_time) {
750                event.size = erf_read_packet(libtrace, packet);
751                if (event.size < 1)
752                        event.type = TRACE_EVENT_TERMINATE;
753                else
754                        event.type = TRACE_EVENT_PACKET;
755                return event;
756               
757        } else {
758                /* Otherwise, use the generic event function */
759                return trace_event_trace(libtrace, packet);
760        }
761       
762}
763
764static uint64_t erf_get_dropped_packets(libtrace_t *trace)
765{
766        if (trace->format_data == NULL)
767                return (uint64_t)-1;
768        return DATA(trace)->drops;
769}
770
771static void erf_help(void) {
772        printf("erf format module: $Revision: 1752 $\n");
773        printf("Supported input URIs:\n");
774        printf("\terf:/path/to/file\t(uncompressed)\n");
775        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
776        printf("\terf:-\t(stdin, either compressed or not)\n");
777        printf("\terf:/path/to/socket\n");
778        printf("\n");
779        printf("\te.g.: erf:/tmp/trace\n");
780        printf("\n");
781        printf("Supported output URIs:\n");
782        printf("\terf:path/to/file\t(uncompressed)\n");
783        printf("\terf:/path/to/file.gz\t(gzip-compressed)\n");
784        printf("\terf:-\t(stdout, either compressed or not)\n");
785        printf("\n");
786        printf("\te.g.: erf:/tmp/trace\n");
787        printf("\n");
788
789       
790}
791
792static struct libtrace_format_t erfformat = {
793        "erf",
794        "$Id$",
795        TRACE_FORMAT_ERF,
796        NULL,                           /* probe filename */
797        erf_probe_magic,                /* probe magic */
798        erf_init_input,                 /* init_input */       
799        erf_config_input,               /* config_input */
800        erf_start_input,                /* start_input */
801        NULL,                           /* pause_input */
802        erf_init_output,                /* init_output */
803        erf_config_output,              /* config_output */
804        erf_start_output,               /* start_output */
805        erf_fin_input,                  /* fin_input */
806        erf_fin_output,                 /* fin_output */
807        erf_read_packet,                /* read_packet */
808        erf_prepare_packet,             /* prepare_packet */
809        NULL,                           /* fin_packet */
810        erf_write_packet,               /* write_packet */
811        erf_get_link_type,              /* get_link_type */
812        erf_get_direction,              /* get_direction */
813        erf_set_direction,              /* set_direction */
814        erf_get_erf_timestamp,          /* get_erf_timestamp */
815        NULL,                           /* get_timeval */
816        NULL,                           /* get_timespec */
817        NULL,                           /* get_seconds */
818        erf_seek_erf,                   /* seek_erf */
819        NULL,                           /* seek_timeval */
820        NULL,                           /* seek_seconds */
821        erf_get_capture_length,         /* get_capture_length */
822        erf_get_wire_length,            /* get_wire_length */
823        erf_get_framing_length,         /* get_framing_length */
824        erf_set_capture_length,         /* set_capture_length */
825        NULL,                           /* get_received_packets */
826        NULL,                           /* get_filtered_packets */
827        erf_get_dropped_packets,        /* get_dropped_packets */
828        NULL,                           /* get_captured_packets */
829        NULL,                           /* get_fd */
830        erf_event,                      /* trace_event */
831        erf_help,                       /* help */
832        NULL                            /* next pointer */
833};
834
835static struct libtrace_format_t rawerfformat = {
836        "rawerf",
837        "$Id$",
838        TRACE_FORMAT_RAWERF,
839        NULL,                           /* probe filename */
840        NULL,           /* probe magic */
841        erf_init_input,                 /* init_input */       
842        erf_config_input,               /* config_input */
843        rawerf_start_input,             /* start_input */
844        NULL,                           /* pause_input */
845        erf_init_output,                /* init_output */
846        erf_config_output,              /* config_output */
847        erf_start_output,               /* start_output */
848        erf_fin_input,                  /* fin_input */
849        erf_fin_output,                 /* fin_output */
850        erf_read_packet,                /* read_packet */
851        erf_prepare_packet,             /* prepare_packet */
852        NULL,                           /* fin_packet */
853        erf_write_packet,               /* write_packet */
854        erf_get_link_type,              /* get_link_type */
855        erf_get_direction,              /* get_direction */
856        erf_set_direction,              /* set_direction */
857        erf_get_erf_timestamp,          /* get_erf_timestamp */
858        NULL,                           /* get_timeval */
859        NULL,                           /* get_timespec */
860        NULL,                           /* get_seconds */
861        erf_seek_erf,                   /* seek_erf */
862        NULL,                           /* seek_timeval */
863        NULL,                           /* seek_seconds */
864        erf_get_capture_length,         /* get_capture_length */
865        erf_get_wire_length,            /* get_wire_length */
866        erf_get_framing_length,         /* get_framing_length */
867        erf_set_capture_length,         /* set_capture_length */
868        NULL,                           /* get_received_packets */
869        NULL,                           /* get_filtered_packets */
870        erf_get_dropped_packets,        /* get_dropped_packets */
871        NULL,                           /* get_captured_packets */
872        NULL,                           /* get_fd */
873        erf_event,                      /* trace_event */
874        erf_help,                       /* help */
875        NULL                            /* next pointer */
876};
877
878
879
880void erf_constructor(void) {
881        register_format(&erfformat);
882        register_format(&rawerfformat);
883}
Note: See TracBrowser for help on using the repository browser.